Using Video Capabilities

The following examples demonstrate how to use the video capabilities of the most recent version of the Dolby.io Communications SDK for Web.

Join a conference with video off

// Create a new conference or get the conference object from the ID
const conference = await VoxeetSDK.conference.fetch('conferenceId');

const constraints = {
    audio: true,
    video: false, // No video on join
};

await VoxeetSDK.conference.join(conference, { constraints: constraints });

Join a conference with video on

// Create a new conference or get the conference object from the ID
const conference = await VoxeetSDK.conference.fetch('conferenceId');

// Let the browser decide what video resolution will be used
let constraints = {
    audio: true,
    video: true,
};

// Video resolution as close to 1280x720 as possible
constraints = {
    audio: true,
    video: {
        width: 1280,
        height: 720,
    },
};

// Video resolution in the range of 640x480 to 1280x720
constraints = {
    audio: true,
    video: {
        width: {
            min: 640,
            max: 1280,
        },
        height: {
            min: 480,
            max: 720,
        },
    },
};

// Video resolution exactly 1280x720
constraints = {
    audio: true,
    video: {
        width: {
            exact: 1280,
        },
        height: {
            exact: 720,
        },
    },
};

await VoxeetSDK.conference.join(conference, { constraints: constraints });

Turn on the video while in a conference

await VoxeetSDK.video.local.start();

You can also specify the video constraints.

const videoConstraints = {
    width: 1280,
    height: 720,
};

await VoxeetSDK.video.local.start(videoConstraints);

This action will trigger the following event:

VoxeetSDK.video.local.on('videoStarted', (mediaStreamTrack) => {

});

If you are connected to a conference and your audio is on, the following event will also be triggered:

VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
    if (stream.getVideoTracks().length) {
        // Add a video element to the UI for the `participant`
    }
});

If you are connected to a conference and your audio is stopped (not muted), the following event will also be triggered:

VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
    if (stream.getVideoTracks().length) {
        // Add a video element to the UI for the `participant`
    }
});

Request the video from a remote participant

const remoteParticipant = VoxeetSDK.conference.participants.get('PARTICIPANT_ID');

await VoxeetSDK.video.remote.start(remoteParticipant);

If the local participant already receives the audio from the remote participant, the following event will be triggered:

VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
    if (stream.getVideoTracks().length) {
        // Add the video element to the UI for the `participant`
    }
});

If the local participant does not receive the audio from the remote participant, the following event will be triggered:

VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
    if (stream.getVideoTracks().length) {
        // Add the video element to the UI for the `participant`
    }
});

Turn off the video for the local participant

await VoxeetSDK.video.local.stop();

This action will trigger the following event:

VoxeetSDK.video.local.on('videoStopped', (mediaStreamTrack) => {

});

If you are connected to a conference and your audio is still on, the following event will also be triggered:

VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
    if (!stream.getVideoTracks().length) {
        // Remove the video element from the UI for the `participant`
    }
});

If you are connected to a conference and your audio is stopped (not muted), the following event will also be triggered:

VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
    // Remove the video element from the UI for the `participant`
});

Stop receiving the video of a remote participant

const remoteParticipant = VoxeetSDK.conference.participants.get('PARTICIPANT_ID');

await VoxeetSDK.video.remote.stop(remoteParticipant);

If the local participant receives the audio from the remote participant, the following event will be triggered:

VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
    if (!stream.getVideoTracks().length) {
        // Remove the video element from the UI for the `participant`
    }
});

If the local participant does not receive the audio from the remote participant, the following event will be triggered:

VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
    // Remove the video element from the UI for the `participant`
});

Change the video resolution

// New resolution constraints
const videoConstraints = {
    width: 1280,
    height: 720,
};

await VoxeetSDK.video.local.applyConstraints(videoConstraints);

Turn on background blur

You do not need to be connected to a conference to turn on the background blur, instead this API allows you to get a preview of your camera before joining the conference.

const processorOptions = {
    virtualBackground: 'bokeh',
};
await VoxeetSDK.video.local.setProcessor(processorOptions);

You can also turn on the video and set a video processor at the same time.

const videoConstraints = {
    width: 1280,
    height: 720,
};
const processorOptions = {
    virtualBackground: 'bokeh',
};

await VoxeetSDK.video.local.start(videoConstraints, processorOptions);

Set an image as virtual background

Replace your background with an image. The image needs to be loaded before enabling the processor.

// Select an image
// <img id="img-for-background" src="path-to-image.jpg" />
const image = document.getElementById('img-for-background'); // must be a type of HTMLImageElement
// Select the virtualBackground option and provide an image
const processorOptions = {
    virtualBackground: image,
};
// Replace the participant's background with your image
await VoxeetSDK.video.local.setProcessor(processorOptions);

If you do not have the image loaded in the DOM, you can also download it and use it for the processor.

// Download the image
const imgDl = await fetch("path-to-image.jpeg");
const blob = await imgDl.blob();
const image = new Image();
image.src = URL.createObjectURL(blob);
await image.decode();

// Select the virtualBackground option and provide an image
const processorOptions = {
    virtualBackground: image,
};
// Replace the participant's background with your image
await VoxeetSDK.video.local.setProcessor(processorOptions);

For more information, see the Video Processing guide.

Set a video as virtual background

Replace your background with a video.

// Select a video
// <video id="video-for-background" src="path-to-video.mp4" loop autoplay muted />
const someUserVideo = document.getElementById('video-for-background'); // must be a type of HTMLVideoElement
// Select the virtualBackground option and provide a video
const processorOptions = {
    virtualBackground: someUserVideo,
};
// Replace the participant's background with your video
await VoxeetSDK.video.local.setProcessor(processorOptions);

For more information, see the Video Processing guide.

Turn off video filter

Disable the video processor engine and release the resources. If you are connected to a conference, you might notice the video flickering once. Turning on the video processor after this call will take a few milliseconds for the system to load the resources and start processing the video.

await VoxeetSDK.video.local.disableProcessing();

Remove the video processor but does not release the resources. This allows for a quick switch back to another video processor. You will not see any flickering of the video while setting no video processing.

await VoxeetSDK.video.local.setProcessor({});

Inject a custom video into the conference

The custom video injection requires a video track. You can get a video track by using an external library or by simply painting a canvas element and capturing a video stream out of it.

// Get a video track out of a canvas at 25 frames per second
const videoTrack = canvasLocalVideo.captureStream(25).getVideoTracks()[0];

Join the conference with a custom video track in the join options.

// Create a new conference or get the conference object from the ID
const conference = await VoxeetSDK.conference.fetch('conferenceId');

const joinOptions = {
    constraints: {
        audio: true,
        video: true,
    },
    customVideoTrack: videoTrack,
};

await VoxeetSDK.conference.join(conference, joinOptions);

Start sending a custom video in the conference:

await VoxeetSDK.video.local.start(videoTrack);

Start a screenshare

await VoxeetSDK.conference.startScreenShare();

This will trigger the following event for all participants:

VoxeetSDK.conference.on('streamAdded', (participant, stream) => {
    if (stream.type === 'ScreenShare') {
        // Add a video element to the UI with the stream as source
    }
});

Stop a screenshare

await VoxeetSDK.conference.stopScreenShare();

This will trigger the following event for all participants:

VoxeetSDK.conference.on('streamRemoved', (participant, stream) => {
    if (stream.type === 'ScreenShare') {
        // Remove the screenshare element from the UI
    }
});