DEV Community

Kishan Nakrani for Video SDK

Posted on • Originally published at videosdk.live on

Integrate Screen Share in JavaScript Video Chat App

Image description

πŸ“Œ Introduction

Integrating screen sharing into your JavaScript video chat app expands its capabilities, allowing users to share their screens during calls. This feature enhances collaboration by enabling participants to show presentations, documents, or other content directly from their screens. With seamless integration, users can easily switch between video chat and screen-sharing modes, making discussions more interactive and productive.

Benefits of Integrating Screen Share in a JavaScript Video Chat App:

  1. Enhanced Collaboration: Screen sharing facilitates real-time collaboration by allowing users to share their screens, enabling them to demonstrate concepts, share documents, or provide visual instructions during video calls.
  2. Improved Communication: Visual aids provided by screen sharing enhance communication clarity, ensuring that all participants are on the same page, reducing misunderstandings, and improving overall comprehension.
  3. Interactive Learning: In educational settings, screen sharing facilitates interactive learning experiences, enabling instructors to demonstrate concepts, showcase multimedia content, or lead virtual workshops effectively.

In the below-provided guide, you'll be able to implement screen-sharing functionality smoothly into your app using JavaScript with VideoSDK.

πŸš€ Getting Started with VideoSDK

To take advantage of Screen Share functionality, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, let's ensure you complete the necessary prerequisites.

Create a VideoSDK Account

Go to your VideoSDK dashboard and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.

Generate your Auth Token

Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the provided tutorial.

Prerequisites

Before proceeding, ensure that your development environment meets the following requirements:

  • VideoSDK Developer Account (if you do not have one, follow VideoSDK Dashboard)
  • Have Node and NPM installed on your device.

πŸ› οΈ Install VideoSDK

Import VideoSDK using the <script> tag or install it using the following npm command. Make sure you are in your app directory before you run this command.

<html>
  <head>
    <!--.....-->
  </head>
  <body>
    <!--.....-->
    <script src="https://sdk.videosdk.live/js-sdk/0.0.85/videosdk.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode
  • npm
npm install @videosdk.live/js-sdk
Enter fullscreen mode Exit fullscreen mode
  • Yarn
yarn add @videosdk.live/js-sdk
Enter fullscreen mode Exit fullscreen mode

Structure of the project

Your project structure should look like this.

  root
   β”œβ”€β”€ index.html
   β”œβ”€β”€ config.js
   β”œβ”€β”€ index.js
Enter fullscreen mode Exit fullscreen mode

You will be working on the following files:

  • index.html: Responsible for creating a basic UI.
  • config.js: Responsible for storing the token.
  • index.js: Responsible for rendering the meeting view and the join meeting functionality.

πŸŽ₯ Essential Steps to Implement Video Call Functionality

Once you've successfully installed VideoSDK in your project, you'll have access to a range of functionalities for building your video call application. Screen Share is one such feature that leverages VideoSDK's capabilities. It leverages VideoSDK's capabilities to identify the user with the strongest audio signal (the one speaking)

Step 1: Design the user interface (UI)​

Create an HTML file containing the screens, join-screen and grid-screen.

<!DOCTYPE html>
<html>
  <head> </head>

  <body>
    <div id="join-screen">
      <!-- Create new Meeting Button -->
      <button id="createMeetingBtn">New Meeting</button>
      OR
      <!-- Join existing Meeting -->
      <input type="text" id="meetingIdTxt" placeholder="Enter Meeting id" />
      <button id="joinBtn">Join Meeting</button>
    </div>

    <!-- for Managing meeting status -->
    <div id="textDiv"></div>

    <div id="grid-screen" style="display: none">
      <!-- To Display MeetingId -->
      <h3 id="meetingIdHeading"></h3>

      <!-- Controllers -->
      <button id="leaveBtn">Leave</button>
      <button id="toggleMicBtn">Toggle Mic</button>
      <button id="toggleWebCamBtn">Toggle WebCam</button>

      <!-- render Video -->
      <div class="row" id="videoContainer"></div>
    </div

      <!-- render Screen Share Video -->
      <div class="row" id="screenShareVideoContainer"></div>

    <!-- Add VideoSDK script -->
    <script src="https://sdk.videosdk.live/js-sdk/0.0.85/videosdk.js"></script>
    <script src="config.js"></script>
    <script src="index.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Step 2: Implement Join Screen​

Configure the token in the config.js file, which you can obtain from the VideoSDK Dashboard.

// Auth token will be used to generate a meeting and connect to it
TOKEN = "Your_Token_Here";
Enter fullscreen mode Exit fullscreen mode

Next, retrieve all the elements from the DOM and declare the following variables in the index.js file. Then, add an event listener to the join and create meeting buttons.

// Getting Elements from DOM
const joinButton = document.getElementById("joinBtn");
const enableScreenShareButton = document.getElementById("enableScreenShareBtn");
const disableScreenShareButton = document.getElementById(
  "disableScreenShareBtn"
);
const leaveButton = document.getElementById("leaveBtn");
const toggleMicButton = document.getElementById("toggleMicBtn");
const toggleWebCamButton = document.getElementById("toggleWebCamBtn");
const createButton = document.getElementById("createMeetingBtn");
const videoContainer = document.getElementById("videoContainer");
const screenShareVideoContainer = document.getElementById(
  "screenShareVideoContainer"
);
const textDiv = document.getElementById("textDiv");

// Declare Variables
let meeting = null;
let meetingId = "";
let isMicOn = false;
let isWebCamOn = false;

function initializeMeeting() {}

function createLocalParticipant() {}

function createVideoElement() {}

function createAudioElement() {}

function setTrack() {}

// Join Meeting Button Event Listener
joinButton.addEventListener("click", async () => {
  document.getElementById("join-screen").style.display = "none";
  textDiv.textContent = "Joining the meeting...";

  roomId = document.getElementById("meetingIdTxt").value;
  meetingId = roomId;

  initializeMeeting();
});

// Create Meeting Button Event Listener
createButton.addEventListener("click", async () => {
  document.getElementById("join-screen").style.display = "none";
  textDiv.textContent = "Please wait, we are joining the meeting";

  // API call to create meeting
  const url = `https://api.videosdk.live/v2/rooms`;
  const options = {
    method: "POST",
    headers: { Authorization: TOKEN, "Content-Type": "application/json" },
  };

  const { roomId } = await fetch(url, options)
    .then((response) => response.json())
    .catch((error) => alert("error", error));
  meetingId = roomId;

  initializeMeeting();
});
Enter fullscreen mode Exit fullscreen mode

Step 3: Initialize Meeting​

Following that, initialize the meeting using the initMeeting() function and proceed to join the meeting.

// Initialize meeting
function initializeMeeting() {
  window.VideoSDK.config(TOKEN);

  meeting = window.VideoSDK.initMeeting({
    meetingId: meetingId, // required
    name: "Thomas Edison", // required
    micEnabled: true, // optional, default: true
    webcamEnabled: true, // optional, default: true
  });

  meeting.join();

  // Creating local participant
  createLocalParticipant();

  // Setting local participant stream
  meeting.localParticipant.on("stream-enabled", (stream) => {
    setTrack(stream, null, meeting.localParticipant, true);
  });

  // meeting joined event
  meeting.on("meeting-joined", () => {
    textDiv.style.display = "none";
    document.getElementById("grid-screen").style.display = "block";
    document.getElementById(
      "meetingIdHeading"
    ).textContent = `Meeting Id: ${meetingId}`;
  });

  // meeting left event
  meeting.on("meeting-left", () => {
    videoContainer.innerHTML = "";
  });

  // Remote participants Event
  // participant joined
  meeting.on("participant-joined", (participant) => {
    // ...
  });

  // participant left
  meeting.on("participant-left", (participant) => {
    // ...
  });
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the Media Elements​

In this step, Create a function to generate audio and video elements for displaying both local and remote participants. Set the corresponding media track based on whether it's a video or audio stream.

// creating video element
function createVideoElement(pId, name) {
  let videoFrame = document.createElement("div");
  videoFrame.setAttribute("id", `f-${pId}`);
  videoFrame.style.width = "300px";


  //create video
  let videoElement = document.createElement("video");
  videoElement.classList.add("video-frame");
  videoElement.setAttribute("id", `v-${pId}`);
  videoElement.setAttribute("playsinline", true);
  videoElement.setAttribute("width", "300");
  videoFrame.appendChild(videoElement);

  let displayName = document.createElement("div");
  displayName.innerHTML = `Name : ${name}`;

  videoFrame.appendChild(displayName);
  return videoFrame;
}

// creating audio element
function createAudioElement(pId) {
  let audioElement = document.createElement("audio");
  audioElement.setAttribute("autoPlay", "false");
  audioElement.setAttribute("playsInline", "true");
  audioElement.setAttribute("controls", "false");
  audioElement.setAttribute("id", `a-${pId}`);
  audioElement.style.display = "none";
  return audioElement;
}

// creating local participant
function createLocalParticipant() {
  let localParticipant = createVideoElement(
    meeting.localParticipant.id,
    meeting.localParticipant.displayName
  );
  videoContainer.appendChild(localParticipant);
}

// setting media track
function setTrack(stream, audioElement, participant, isLocal) {
  if (stream.kind == "video") {
    isWebCamOn = true;
    const mediaStream = new MediaStream();
    mediaStream.addTrack(stream.track);
    let videoElm = document.getElementById(`v-${participant.id}`);
    videoElm.srcObject = mediaStream;
    videoElm
      .play()
      .catch((error) =>
        console.error("videoElem.current.play() failed", error)
      );
  }
  if (stream.kind == "audio") {
    if (isLocal) {
      isMicOn = true;
    } else {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(stream.track);
      audioElement.srcObject = mediaStream;
      audioElement
        .play()
        .catch((error) => console.error("audioElem.play() failed", error));
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Handle participant events​

Thereafter, implement the events related to the participants and the stream.

The following are the events to be executed in this step:

  1. participant-joined: When a remote participant joins, this event will trigger. In the event callback, create video and audio elements previously defined for rendering their video and audio streams.
  2. participant-left: When a remote participant leaves, this event will trigger. In the event callback, remove the corresponding video and audio elements.
  3. stream-enabled: This event manages the media track of a specific participant by associating it with the appropriate video or audio element.
// Initialize meeting
function initializeMeeting() {
  // ...

  // participant joined
  meeting.on("participant-joined", (participant) => {
    let videoElement = createVideoElement(
      participant.id,
      participant.displayName
    );
    let audioElement = createAudioElement(participant.id);
    // stream-enabled
    participant.on("stream-enabled", (stream) => {
      setTrack(stream, audioElement, participant, false);
    });
    videoContainer.appendChild(videoElement);
    videoContainer.appendChild(audioElement);
  });

  // participants left
  meeting.on("participant-left", (participant) => {
    let vElement = document.getElementById(`f-${participant.id}`);
    vElement.remove(vElement);

    let aElement = document.getElementById(`a-${participant.id}`);
    aElement.remove(aElement);
  });
}
Enter fullscreen mode Exit fullscreen mode

Step 6: Implement Controls​

Next, implement the meeting controls such as toggleMic, toggleWebcam, and leave the meeting.

// leave Meeting Button Event Listener
leaveButton.addEventListener("click", async () => {
  meeting?.leave();
  document.getElementById("grid-screen").style.display = "none";
  document.getElementById("join-screen").style.display = "block";
});

// Toggle Mic Button Event Listener
toggleMicButton.addEventListener("click", async () => {
  if (isMicOn) {
    // Disable Mic in Meeting
    meeting?.muteMic();
  } else {
    // Enable Mic in Meeting
    meeting?.unmuteMic();
  }
  isMicOn = !isMicOn;
});

// Toggle Web Cam Button Event Listener
toggleWebCamButton.addEventListener("click", async () => {
  if (isWebCamOn) {
    // Disable Webcam in Meeting
    meeting?.disableWebcam();

    let vElement = document.getElementById(`f-${meeting.localParticipant.id}`);
    vElement.style.display = "none";
  } else {
    // Enable Webcam in Meeting
    meeting?.enableWebcam();

    let vElement = document.getElementById(`f-${meeting.localParticipant.id}`);
    vElement.style.display = "inline";
  }
  isWebCamOn = !isWebCamOn;
});
Enter fullscreen mode Exit fullscreen mode

You can check out the complete here.

Integrate Screen Share Feature

Screen sharing in a meeting is the process of sharing your computer screen with other participants in the meeting. It allows everyone in the meeting to see exactly what you are seeing on your screen, which can be helpful for presentations, demonstrations, or collaborations.

Enable Screen Share

By using the enableScreenShare() function of the meeting object, the local participant can share their desktop screen to other participants.

  • You can also pass a customised screenshare track in enableScreenShare() by using Custom Screen Share Track.
  • The Screen Share stream of a participant can be accessed from the streams property of the Participant object.

Disable Screen Share

By using disableScreenShare() function of the meeting object, the local participant can stop sharing their desktop screen to other participants.

NOTE: Screen Sharing is only supported in the Desktop browsers and not in mobile/tab browser.

let meeting;

// Initialize Meeting
meeting = VideoSDK.initMeeting({
  // ...
});

enableScreenShareButton.addEventListener("click", () => {
  // Enabling ScreenShare
  meeting?.enableScreenShare();
});

disableScreenShareButton.addEventListener("click", () => {
  // Disabling ScreenShare
  meeting?.disableScreenShare();
});
Enter fullscreen mode Exit fullscreen mode

Events associated with Screen Share

enableScreenShare

  • Every Participant will receive a callback on stream-enabled event of the participant object with Stream object.
  • Every Participant will receive a callback on presenter-changed event of the meeting object with presenterId. <!--kg-card-begin: markdown--> #### disableScreenShare <!--kg-card-end: markdown-->
  • Every Participant will receive a callback on stream-disabled event of the participant object with the Stream object.
  • Every Participant will receive a callback on presenter-changed event of the meeting object with null value indicating there is no current presenter.
let meeting;

// Initialize Meeting
meeting = VideoSDK.initMeeting({
  // ...
});

  // participant joined
  meeting.on("participant-joined", (participant) => {
    // ...
    // ...
    participant.on("stream-enabled", (stream) => {
      setTrack(stream, audioElement, participant, false);

      if (stream.kind == "share") {
        //particiapnt turned on screen share
        //Render screenshare logic here
      }
    });
    // ...
    // ...

   participant.on("stream-disabled", (stream) => {
      if (stream.kind === "share") {
        //particiapnt turned off screenshare
        //remove screenshare logic here
      }
    });
  });

meeting.on("presenter-changed", (presenterId) => {
  if (presenterId) {
    //someone start presenting
  } else {
    //someone stopped presenting
  }
});
Enter fullscreen mode Exit fullscreen mode

Screen Share with Audio

To enable screen sharing with audio, select the Share tab audio option when sharing the chrome tab, as shown below.

How to Integrate Screen Share in JavaScript Video Chat App?

After clicking the Share button, you will receive the selected tab's audio stream in the participant's screenShareAudioStream.

NOTE:

Screen Share with Audio is only supported while sharing Chrome Tab in a Chromium-based browser like Google Chrome, Brave etc.

Rendering Screen Share and Screen Share Audio​

To display the screenshare video stream, you will receive it in the participant's stream-enabled callback with the stream kind set as "share".

participant.on("stream-enabled", (stream) => {
  if (stream.kind == "share") {
  const videoElem = createShareVideoElement(participant.id, stream);

  //add videoElem to your container
  screenShareVideoContainer.appendChild(videoElem);
  }

  if (stream.kind == "shareAudio") {
  }
});

// creating video element
function createShareVideoElement(pId, stream) {
  if (pId == meeting.localParticipant.id) return;

  let videoElement = document.createElement("video");
  videoElement.setAttribute("autoPlay", false);
  videoElement.setAttribute("controls", "false");
  videoElement.setAttribute("id", `v-share-${pId}`);

  const mediaStream = new MediaStream();
  mediaStream.addTrack(stream.track);
  videoElement.srcObject = mediaStream;
  videoElement
    .play()
    .catch((error) => console.error("audioElem.play() failed", error));
  return videoElement;
}

// creating audio element
function createShareAudioElement(pId, stream) {}
Enter fullscreen mode Exit fullscreen mode

Now to render the screenshare audio stream, you will receive it in the participant's stream-enabled callback with the stream kind set as "shareAudio".

participant.on("stream-enabled", (stream) => {
  if (stream.kind == "share") {
  }
  if (stream.kind == "shareAudio") {
    const audioElem = createShareAudioElement(participant.id, stream);

    //add audioElem to your container
    screenShareVideoContainer.appendChild(audioElem);
  }
});

// creating video element
function createShareVideoElement(pId, stream) {}

// creating audio element
function createShareAudioElement(pId, stream) {
  if (pId == meeting.localParticipant.id) return;

  let audioElement = document.createElement("audio");
  audioElement.setAttribute("autoPlay", false);
  audioElement.setAttribute("playsInline", "false");
  audioElement.setAttribute("controls", "false");
  audioElement.setAttribute("id", `a-share-${pId}`);
  audioElement.style.display = "none";

  const mediaStream = new MediaStream();
  mediaStream.addTrack(stream.track);
  audioElement.srcObject = mediaStream;
  audioElement
    .play()
    .catch((error) => console.error("audioElem.play() failed", error));
  return audioElement;
}
Enter fullscreen mode Exit fullscreen mode

πŸ”š Conclusion

Integrating screen sharing into your JavaScript video chat app is a powerful way to enhance communication and collaboration. By enabling users to share their screens during calls, you empower them to demonstrate ideas, share presentations, and collaborate on documents more effectively. With a seamless integration process provided by VideoSDK, implementing screen sharing becomes straightforward, ensuring a smooth user experience. Whether for remote work, online education, or virtual meetings, this feature adds significant value to your app, making it more versatile and engaging for users.

Unlock the full potential of VideoSDK and create seamless video experiences today! Sign up now and get 10,000 free minutes to elevate your video app to the next level.

Top comments (0)