2.2.13. Utility Feeds

2.2.13.1. Overview

A key aspect of SDK feeds are their ability to share audio and video media with other clients or session participants. However, there is a category of feed that we call a utility feed, which is stand-alone and does not require a session. These feeds can be used for a variety of purposes, such as local preview of video input before a session is started.

Utility feeds are created and managed in a similar way to other feeds, but they are typically created using just feed components, properties and settings, and do not require a session object like a MediaServerSession to be created.

Utility feeds can use feed stages like any other feed, see the guide section Feed Stages for more details. SDK releases also include a stages sample that demonstrates how to create and use stages in utility feeds.

2.2.13.2. Local video feed

UtilityVideoLocalFeed takes a video input/source component (e.g. a webcam) and transfers it to a video output component (e.g. a window).

The following snippet shows how to create such a utility feed:

    PxMedia::UtilityVideoLocalFeed::FeedProperties props("webcam-preview");
    PxMedia::VideoInputFeedV4Linux2                input;
    PxMedia::VideoOutputFeedAuto                   output;
    auto created = PxMedia::UtilityVideoLocalFeed::create(pxContext, props, input, output);
    if (!created) {
        // Handle error...
    }
    auto utilityFeed = created.value();

The feed just takes a regular ProximieContext (see the ProximieContext guide), and the two input and output video components. For simplicity we don’t show any additional properties and settings for the components in this example.

Once the feed is created, it is started using startFeed():

    auto started = utilityFeed->startFeed();
    if (!started) {
        // Handle error...
    }

Local video utility feeds support start & stop notifications as callbacks:

    utilityFeed->onFeedStarted(
        [](auto& feed)
        {
            // Feed has started
        });
    utilityFeed->onFeedStopped(
        [](auto& feed, error_code error)
        {
            // Feed has stopped, possibly with an error
            if (error) {
                // Handle error...
            }
        });

Finally, feeds may be stopped using stopFeed():

    auto stopped = utilityFeed->stopFeed();
    if (!stopped) {
        // Handle error...
    }

2.2.13.3. Recording to file

Another utility feed is AVOutputFeedFile, which records video (and optionally audio) to a file on disk. By default, it uses the X264 software encoder, but you can provide a custom encoder such as VAAPI for hardware acceleration.

Recording with default X264 encoder

    // Create a recording with the default X264 encoder
    PxMedia::AVOutputFeedFile::FeedProperties           fileProps("recording");
    PxMedia::AVOutputFeedFile::AVOutputFeedFileSettings settings;
    if (auto err = settings.destinationDirectory("/tmp/recordings")) {
        // Handle error...
    }
    if (auto err = settings.destinationFilenamePattern("video_%02d.mp4")) {
        // Handle error...
    }

    PxMedia::VideoInputFeedV4Linux2   input;
    PxMedia::X264EncoderFeedComponent defaultEncoder(
        PxMedia::AVOutputFeedFile::defaultRecordingEncoder());
    defaultEncoder.bitrate(2000_kbps);

    auto recording =
        PxMedia::AVOutputFeedFile::create(pxContext, fileProps, settings, input, defaultEncoder);

The defaultRecordingEncoder() helper function provides a pre-configured X264 encoder with sensible defaults that you can customize as needed.

Recording with VAAPI hardware encoder

For improved performance on systems with Intel or AMD GPUs, you can use the VAAPI hardware encoder:

    // Create a recording with VAAPI hardware encoder for Intel/AMD GPUs
    PxMedia::AVOutputFeedFile::FeedProperties           filePropsVaapi("recording-vaapi");
    PxMedia::AVOutputFeedFile::AVOutputFeedFileSettings settingsVaapi;
    if (auto err = settingsVaapi.destinationDirectory("/tmp/recordings")) {
        // Handle error...
    }
    if (auto err = settingsVaapi.destinationFilenamePattern("video_vaapi_%02d.mp4")) {
        // Handle error...
    }

    PxMedia::H264VaapiEncoderComponent vaapiEncoder;
    vaapiEncoder.bitrate(2000_kbps);

    PxMedia::VideoInputFeedV4Linux2 inputVaapi;
    auto                            recordingVaapi = PxMedia::AVOutputFeedFile::create(
        pxContext, filePropsVaapi, settingsVaapi, inputVaapi, vaapiEncoder);

For available encoder properties, see X264EncoderFeedComponent and H264VaapiEncoderComponent.

2.2.13.4. Local audio feed

UtilityAudioLocalFeed takes one or more audio input/source component (e.g. a microphone) and transfers it to a audio output component (e.g. a speaker). If it is given multiple inputs they will be mixed together. Inputs can be added and removed dynamically (after creation and regardless of the play/stop state). Audio mixing performs format conversion and resampling as necessary.

Local audio feeds are created and managed in a similar way to other feeds.

The following snippet shows how to create a local audio feed:

    PxMedia::UtilityAudioLocalFeed::FeedProperties props("audio-mixer");
    Proximie::PxMedia::AudioInputFeedTestSignal    inputTestSignal;
    Proximie::PxMedia::AudioInputFeedAuto          inputAuto;
    PxMedia::AudioOutputFeedInter                  outputInter("test-channel");
    auto                                           inputInter = outputInter.makeInput();
    PxMedia::AudioOutputFeedInter                  output("test");

    auto created = PxMedia::UtilityAudioLocalFeed::create(
        pxContext, props, {inputTestSignal, inputInter}, output);
    if (!created) {
        // Handle error...
    }
    auto utilityFeed = created.value();

The feed just takes a regular ProximieContext (see the ProximieContext guide), and 2 input audio components and 1 output audio component. For simplicity we don’t show any additional properties and settings for the components in this example.

Once the feed is created, it is started using startFeed():

    auto started = utilityFeed->startFeed();
    if (!started) {
        // Handle error...
    }

Local audio feeds support adding and removing inputs dynamically after the feed has been created and while it is playing or not playing:

    auto id = utilityFeed->addInput(inputAuto);
    if (!id) {
        // Handle error...
    }
    auto removed = utilityFeed->removeInput(id.value());
    if (!removed) {
        // Handle error...
    }

Local audio feeds support start & stop notifications as callbacks:

    utilityFeed->onFeedStarted(
        [](auto& feed)
        {
            // Feed has started
        });
    utilityFeed->onFeedStopped(
        [](auto& feed, error_code error)
        {
            // Feed has stopped, possibly with an error
            if (error) {
                // Handle error...
            }
        });

Finally, these feeds may be stopped using stopFeed():

    auto stopped = utilityFeed->stopFeed();
    if (!stopped) {
        // Handle error...
    }

All dynamic inputs (those added using addInput()) will be removed when the local audio feed is stopped.