π 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:
- 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.
- 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.
- 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>
- npm
npm install @videosdk.live/js-sdk
- Yarn
yarn add @videosdk.live/js-sdk
Structure of the project
Your project structure should look like this.
root
βββ index.html
βββ config.js
βββ index.js
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>
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";
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();
});
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) => {
// ...
});
}
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));
}
}
}
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:
-
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. -
participant-left
: When a remote participant leaves, this event will trigger. In the event callback, remove the corresponding video and audio elements. -
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);
});
}
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;
});
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 theParticipant
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();
});
Events associated with Screen Share
enableScreenShare
- Every Participant will receive a callback on
stream-enabled
event of theparticipant
object withStream
object. - Every Participant will receive a callback on
presenter-changed
event of the meeting object withpresenterId
. <!--kg-card-begin: markdown--> #### disableScreenShare <!--kg-card-end: markdown--> - Every Participant will receive a callback on
stream-disabled
event of theparticipant
object with theStream
object. - Every Participant will receive a callback on
presenter-changed
event of the meeting object withnull
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
}
});
Screen Share with Audio
To enable screen sharing with audio, select the Share tab audio option when sharing the chrome tab, as shown below.
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) {}
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;
}
π 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)