Integrate Video

This tutorial guides how to add basic video features to an application.

1. Add new buttons to the application layout

Open the index.html file and create the following HTML elements:

  • A div element with the video-container ID, to which a video stream will be dynamically added
  • A div element with the actions ID responsible for buttons with the start-video-btn ID
  • A button element with the stop-video-btn ID located in the actions element
<!-- Step 1: Add buttons responsible for enabling and disabling video -->
<div id="app">
  <div id="form">...</div>
  <div id="actions">
    <button id="start-video-btn" disabled>Start video</button>
    <button id="stop-video-btn" disabled>Stop video</button>
  </div>
  <div id="video-container"></div>
</div>

2. Declare the startVideoBtn and stopVideoBtn variables

Open the ui.js file and declare startVideoBtn and stopVideoBtn in the initUI function. These buttons will be responsible for starting and stopping the local participant's video stream.

/// Step 2: Declare variables responsible for enabling and disabling video
const startVideoBtn = document.getElementById("start-video-btn");
const stopVideoBtn = document.getElementById("stop-video-btn");

3. Edit the joinButton "onclick" function

The function needs to enable the startVideoBtn button when the local participant joins a conference. This way, the local participant will be able to start their video after joining.

/// Step 3: Modify the join function to allow enabling video after joining a conference
joinButton.onclick = () => {
... => VoxeetSDK.conference.join(conference, {}))
    .then(() => {
        // ----->  Enable the button here ------>
        startVideoBtn.disabled = false;
    })
...
};

4. Write an "onclick" handler for startVideoBtn

The handler needs to start video transmission and enable the stopVideoBtn button after calling the start method. This way, the participant will be able to stop transmitting the started video stream.

/// Step 4: Write a handler that starts video transmission and enables the stopVideoBtn button
startVideoBtn.onclick = () => {
  VoxeetSDK.video.local
    .start()
    .then(() => {
      startVideoBtn.disabled = true;
      stopVideoBtn.disabled = false;
    })
    .catch((err) => console.error(err));
};

Note: If you use SDK 3.6 or earlier, use the VoxeetSDK.conference.startVideo method.

5. Write an "onclick" handler for stopVideoBtn

The stopVideoBtn button needs to stop the started video stream and enable the startVideoBtn button after calling the stop method.

/// Step 5: Write a handler that stops the video stream transmission and enables the startVideoBtn button
stopVideoBtn.onclick = () => {
  VoxeetSDK.video.local
    .stop()
    .then(() => {
      startVideoBtn.disabled = false;
      stopVideoBtn.disabled = true;
    })
    .catch((err) => console.error(err));
};

Note: If you use SDK 3.6 or earlier, use the VoxeetSDK.conference.stopVideo method.

6. Write the addVideoNode function

The function needs to be responsible for the dynamic creation of a specific participant's video node element in the HTML DOM.

/// Step 6: Create a video node element in the video-container <div> for a specific participant
const addVideoNode = (participant, stream) => {
  let videoNode = document.getElementById("video-" + participant.id);

  if (!videoNode) {
    videoNode = document.createElement("video");

    videoNode.setAttribute("id", "video-" + participant.id);
    videoNode.setAttribute("height", 240);
    videoNode.setAttribute("width", 320);
    videoNode.setAttribute("playsinline", true);
    videoNode.muted = true;
    videoNode.setAttribute("autoplay", "autoplay");

    const videoContainer = document.getElementById("video-container");
    videoContainer.appendChild(videoNode);
  }

  navigator.attachMediaStream(videoNode, stream);
};

When the local participant joins a conference with audio or video enabled, the SDK emits the streamAdded event to all remote conference participants.

Note: The playsinline attribute used in this example prevents the video from freezing in the Safari browser.

7. Write the removeVideoNode function

The function needs to be responsible for removing specific participant's video elements from the UI.

/// Step 7: Write a function responsible for removing specific video elements from the UI
const removeVideoNode = (participant) => {
  let videoNode = document.getElementById("video-" + participant.id);

  if (videoNode) {
    videoNode.srcObject = null; // Prevent memory leak in Chrome
    videoNode.parentNode.removeChild(videoNode);
  }
};

When the local participant leaves a conference, the SDK emits the streamRemoved event to all remote conference participants.

8. Call addVideoNode after receiving the streamAdded and streamUpdated events

Open the client.js file and call addVideoNode upon receiving the streamAdded and streamUpdated events in the main function.

/// Step 8: Add event handlers that call addVideoNode after receiving the streamAdded and streamUpdated events
VoxeetSDK.conference.on("streamAdded", (participant, stream) => {
  if (stream.type === "ScreenShare") return;

  if (stream.getVideoTracks().length) {
    addVideoNode(participant, stream);
  }
});

VoxeetSDK.conference.on("streamUpdated", (participant, stream) => {
  if (stream.type === "ScreenShare") return;

  if (stream.getVideoTracks().length) {
    addVideoNode(participant, stream);
  } else {
    removeVideoNode(participant);
  }
});

9. Call removeVideoNode after receiving the streamRemoved event

In the same file, call removeVideoNode in the main function upon receiving the streamRemoved event.

/// Step 9: Add an event handler that calls removeVideoNode after receiving the streamRemoved events
VoxeetSDK.conference.on("streamRemoved", (participant, stream) => {
  removeVideoNode(participant);
});

After these steps, you should see in your application the added buttons and be able to start and stop your video stream.


What’s Next