100ms Logo

100ms

Docs

Search docs
/

JavaScript Quickstart Guide

Overview

This guide will walk you through step-by-step instructions to create a video conferencing application using the 100ms JavaScript SDK and test it locally on your device. If you plan to use React, do check our React quickstart as well.

Please check our basic concepts guide to understand the concepts like rooms, templates, peers, etc.

TL;DR - Try out this complete example in CodeSandbox.

Create a sample app locally

In this section, we will walk you through a complete code example that will enable you to create a local video-conferencing application in under 10 minutes and test audio/video functionality along with a couple of other essential functionalities like mute/unmute audio and video.

We will use ParcelJS, a web application bundler that requires zero configuration. If you wish to use any other library or framework, you can set up your app using that.

Initialize a project

You can initialize a project using npm init or yarn init. While initializing the project you can enter the details for your project as you wish.

Install ParcelJS & 100ms SDK

Then, install ParcelJS and 100ms SDK into your app like below

  • using yarn:
    yarn add --dev parcel yarn add @100mslive/hms-video-store
  • using npm:
    npm install --save-dev parcel npm install @100mslive/hms-video-store

Project setup

Now that the dependencies are installed, let's create basic source files for our video-conferencing application. Let's create the files and folders in the below manner:

100ms-test - index.html - src - index.js - styles.css

Complete code example

Next, copy the below code snippets and paste it into the respective files created in the above step.

index.js
import { HMSReactiveStore, selectIsLocalAudioEnabled, selectIsLocalVideoEnabled, selectPeers, selectIsConnectedToRoom, selectVideoTrackByID, } from "@100mslive/hms-video-store"; // Initialize HMS Store const hmsManager = new HMSReactiveStore(); hmsManager.triggerOnSubscribe(); const hmsStore = hmsManager.getStore(); const hmsActions = hmsManager.getActions(); // HTML elements const form = document.getElementById("join"); const joinBtn = document.getElementById("join-btn"); const conference = document.getElementById("conference"); const peersContainer = document.getElementById("peers-container"); const leaveBtn = document.getElementById("leave-btn"); const muteAudio = document.getElementById("mute-aud"); const muteVideo = document.getElementById("mute-vid"); const controls = document.getElementById("controls"); // store peer IDs already rendered to avoid re-render on mute/unmute const renderedPeerIDs = new Set(); // Joining the room joinBtn.onclick = () => { hmsActions.join({ userName: document.getElementById("name").value, authToken: document.getElementById("token").value }); }; // Leaving the room function leaveRoom() { hmsActions.leave(); } // Cleanup if user refreshes the tab or navigates away window.onunload = window.onbeforeunload = leaveRoom; leaveBtn.onclick = leaveRoom; // Helper function to create html elements function createElementWithClass(tag, className) { const newElement = document.createElement(tag); newElement.className = className; return newElement; } // Render a single peer function renderPeer(peer) { const peerTileDiv = createElementWithClass("div", "peer-tile"); const videoElement = createElementWithClass("video", "peer-video"); const peerTileName = createElementWithClass("div", "peer-name"); videoElement.autoplay = true; videoElement.muted = true; videoElement.playsinline = true; peerTileName.textContent = peer.name; hmsStore.subscribe((track) => { if (!track) { return; } if (track.enabled) { hmsActions.attachVideo(track.id, videoElement); } else { hmsActions.detachVideo(track.id, videoElement); } }, selectVideoTrackByID(peer.videoTrack)); peerTileDiv.append(videoElement); peerTileDiv.append(peerTileName); renderedPeerIDs.add(peer.id); return peerTileDiv; } // display a tile for each peer in the peer list function renderPeers() { const peers = hmsStore.getState(selectPeers); peers.forEach((peer) => { if (!renderedPeerIDs.has(peer.id) && peer.videoTrack) { peersContainer.append(renderPeer(peer)); } }); } // Reactive state - renderPeers is called whenever there is a change in the peer-list hmsStore.subscribe(renderPeers, selectPeers); // Mute and unmute audio muteAudio.onclick = async () => { const audioEnabled = !hmsStore.getState(selectIsLocalAudioEnabled); await hmsActions.setLocalAudioEnabled(audioEnabled); muteAudio.textContent = audioEnabled ? "Mute" : "Unmute"; }; // Mute and unmute video muteVideo.onclick = async () => { const videoEnabled = !hmsStore.getState(selectIsLocalVideoEnabled); await hmsActions.setLocalVideoEnabled(videoEnabled); muteVideo.textContent = videoEnabled ? "Hide" : "Unhide"; }; // Showing the required elements on connection/disconnection function onConnection(isConnected) { if (isConnected) { form.classList.add("hide"); conference.classList.remove("hide"); leaveBtn.classList.remove("hide"); controls.classList.remove("hide"); } else { form.classList.remove("hide"); conference.classList.add("hide"); leaveBtn.classList.add("hide"); controls.classList.add("hide"); } } // Listen to the connection state hmsStore.subscribe(onConnection, selectIsConnectedToRoom);

Test the app

To test the application, run the application using:

  • using Yarn yarn parcel 100ms-test/index.html --port 3000 or
  • when using npm, run npx parcel index.html --port 3000.

This will start your development server in http://localhost:3000/. Open this in your browser to test the video conferencing app you created above.

Fetch token to join the room

To test audio/video functionality, you need to connect to a 100ms room; please check following steps for the same:

  1. Navigate to your 100ms dashboard or create an account if you don't have one.

  2. Use the Video Conferencing Starter Kit to create a room with a default template assigned to it to test this app quickly.

  3. Go to Rooms page in your dashboard, click on the Room Id of the room you created above, and click on the Join room button on the top right.

  4. You will see two 100ms demo URLs for two roles created when you deployed the starter kit; you can click on the 'key' icon to copy the token and use the same to join the room in your browser.

    Join room key

Now, after you click join, you should be able to see yourself!


You can open the app in another tab in the browser to join as the second peer to check audio/video transactions between two or more peers.


We have a fully functional video conferencing application now šŸŽ‰šŸš€

Building step-by-step

In this section, let's walk through what the code does.

Initialize the SDK

Let us start with initializing the libraries. We need two instances to get started:

  • An instance of HMSStore that holds the complete state of the application such as details of all the participants. We can also visualize this state at any time using the DevTools extension.
    • This HMSStore is a single source of truth for the entire SDK. To get access to the data from this store, you have to call hmsStore.subscribe(). It takes two parameters. A callback and a selector which tells the store which slice of state you want to subscribe to.
    • The subscribe() also returns a reference to unsubscribe() which could be used later to ubsubscribe from the subscription.
  • And an instance of HMSActions that will help us perform actions such as joining the room, muting our audio, and sending messages.
index.js
import { HMSReactiveStore, selectIsLocalAudioEnabled, selectIsLocalVideoEnabled, selectPeers, selectIsConnectedToRoom } from "@100mslive/hms-video-store"; // Initialize HMS Store const hmsManager = new HMSReactiveStore(); hmsManager.triggerOnSubscribe(); const hmsStore = hmsManager.getStore(); const hmsActions = hmsManager.getHMSActions();

Initialize the HTML elements

Now, let's initialize all the HTML elements required such as tile for local and remote peers, join and leave button, mute and unmute button, etc.

index.js
// HTML elements const form = document.getElementById("join"); const joinBtn = document.getElementById("join-btn"); const conference = document.getElementById("conference"); const peersContainer = document.getElementById("peers-container"); const leaveBtn = document.getElementById("leave-btn"); const muteAudio = document.getElementById("mute-aud"); const muteVideo = document.getElementById("mute-vid"); const controls = document.getElementById("controls");

Join/leave a room

To join a room (a video call), we need to call the join method on hmsActions and it requires us to pass a config object. The config object must be passed the following fields:

  • userName: The name of the user. This is the value that will be set on the peer object and be visible to everyone connected to the room.
  • authToken: A client-side token that is used to authenticate the user. You can read about how to generate this token here.

Let's use a form to request both of these fields from the user for our application.

Let's include a way for people to leave the room as well. To leave the room, we can use the hmsActions leave method. We'll set up the leave method to be called whenever the user closes the window or refreshes the tab.

index.js
// Joining the room joinBtn.onclick = () => { hmsActions.join({ userName: document.getElementById("name").value, authToken: document.getElementById("token").value }); }; // Leaving the room function leaveRoom() { hmsActions.leave(); } // Cleanup if user refreshes the tab or navigates away window.onunload = window.onbeforeunload = leaveRoom; leaveBtn.onclick = leaveRoom;

Render video tiles for peers

Let us next add a way to show a tile for every participant in the room. We'll need a list of peers connected to the room.

  • We will use the attachVideo method on hmsActions to add the video from an element for a track ID.
  • And selectPeers selector from hmsStore
index.js
// Helper function to create html elements function createElementWithClass(tag, className) { const newElement = document.createElement(tag); newElement.className = className; return newElement; } // Render a single peer function renderPeer(peer) { const peerTileDiv = createElementWithClass("div", "peer-tile"); const videoElement = createElementWithClass("video", "peer-video"); const peerTileName = createElementWithClass("span", "peer-name"); videoElement.autoplay = true; videoElement.muted = true; videoElement.playsinline = true; peerTileName.textContent = peer.name; hmsActions.attachVideo(peer.videoTrack, videoElement); peerTileDiv.append(videoElement); peerTileDiv.append(peerTileName); return peerTileDiv; } // Display a tile for each peer in the peer list function renderPeers() { peersContainer.innerHTML = ""; const peers = hmsStore.getState(selectPeers); peers.forEach((peer) => { if (peer.videoTrack) { peersContainer.append(renderPeer(peer)); } }); } // Reactive state - renderPeers is called whenever there is a change in the peer-list hmsStore.subscribe(renderPeers, selectPeers);

Mute/unmute local tracks

Right now we are publishing both audio and video feed of the user whenever they join the room. We may want to allow the user to mute/unmute their own tracks - both audio and video.

Let's add 2 buttons on the bottom of the page and call the setLocalAudioEnabled method on hmsActions to mute/unmute the local audio tracks and setLocalVideoEnabled method on hmsActions to mute/unmute the local video tracks.

index.js
// Mute and unmute audio muteAudio.onclick = () => { const audioEnabled = !hmsStore.getState(selectIsLocalAudioEnabled); hmsActions.setLocalAudioEnabled(audioEnabled); muteAudio.textContent = audioEnabled ? "Mute" : "Unmute"; }; // Mute and unmute video muteVideo.onclick = () => { const videoEnabled = !hmsStore.getState(selectIsLocalVideoEnabled); hmsActions.setLocalVideoEnabled(videoEnabled); muteVideo.textContent = videoEnabled ? "Hide" : "Unhide"; // Re-render video tile renderPeers(); };

Change UI based on connection state

Right now, our join form will show up even after we have joined the room. We need a way to know the connection state of the room and hide the form after we've connected.

We can do this by subscribing to the store with the selectIsConnectedToRoom selector from hmsStore.

index.js
// Showing the required elements on connection/disconnection function onConnection(isConnected) { if (isConnected) { form.classList.add("hide"); conference.classList.remove("hide"); leaveBtn.classList.remove("hide"); controls.classList.remove("hide"); } else { form.classList.remove("hide"); conference.classList.add("hide"); leaveBtn.classList.add("hide"); controls.classList.add("hide"); } } // Listen to the connection state hmsStore.subscribe(onConnection, selectIsConnectedToRoom);

Refer to Test the app section above to test your sample app locally.

Next steps

Here's the complete example.

There is also a version of the above quickstart using CDN here.

That wraps it up for this guide. We hope you had fun. There are plenty of cool stuff which can be done with our SDK, be sure to check the features section for more information.

You can also check out our React demo app built with more features like screenshare, virtual background, noise suppression, audio/video playlist, etc.


Have a suggestion? Recommend changes ->

Was this helpful?

1234