Skip to contentSkip to navigationSkip to topbar
On this page

Getting Started: JavaScript


(warning)

Warning

This documentation is for reference only. We are no longer onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2026(link takes you to an external page).

We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide(link takes you to an external page) to assist you in minimizing any service disruption.

This guide provides you with an overview of how to build your video application with the Twilio Programmable Video JavaScript SDK.

(information)

Info

If you haven't already done so, take a look at the open source video collaboration app(link takes you to an external page) and quickstart apps(link takes you to an external page). Then come back to this guide for more detail on how to add video to your own app.


Video API Overview

video-api-overview page anchor

Let's start with an overview of the Programmable Video API:

  • A Room represents a real-time audio, data, video, and/or screen-share session, and is the basic building block for a Programmable Video application.
  • Participants represent client applications that are connected to a Room and sharing audio, data, and/or video media with one another.
  • Tracks represent the individual audio, data, and video media streams that are shared within a Room.
  • LocalTracks represent the audio, data, and video captured from the local client's media sources (for example, microphone and camera).
  • RemoteTracks represent the audio, data, and video tracks from other participants connected to the Room.

The following code samples illustrate common tasks that you as a developer may wish to perform related to a Room and its Participants.


1. Get the Programmable Video JavaScript SDK

1-get-the-programmable-video-javascript-sdk page anchor

You can install the JavaScript Video library using NPM(link takes you to an external page).

NPM

npm page anchor
npm install twilio-video --save

You can also include it in your application using the CDN.

Releases of twilio-video.js are hosted on a CDN, and you can include these directly in your web app using a <script> tag.

<script src="//sdk.twilio.com/js/video/releases/2.17.1/twilio-video.min.js"></script>

Using this method, twilio-video.js will set a browser global:

const Video = Twilio.Video;

Please refer to this table for information regarding supported browsers and operating systems.

API Keys represent credentials to access the Twilio API. You use them to:

Follow the instructions in the API Keys Overview doc to create a new API key for your project.

3. Generate an Access Token

3-generate-an-access-token page anchor

To execute the code samples below, you'll need to generate an Access Token. An Access Token is a short-lived credential used to authenticate your client-side application to Twilio.

You can generate an Access Token using either the Twilio CLI or a Twilio Helper Library.

For application testing purposes, the Twilio CLI provides a quick way to generate Access Tokens that you can then copy/paste into your application. In a production application, you should use the Twilio Helper Libraries because your back-end server will need to generate an Access Token for every user in your application.

To use the CLI, you will need to install the Twilio CLI and log in to your Twilio account from the command line; see the CLI Quickstart for instructions. Then, you can install the Token CLI plugin(link takes you to an external page) with the following command:

twilio plugins:install @twilio-labs/plugin-token

To generate an Access Token, run the following command. --identity is a required argument and should be a string that represents the user identity for this Access Token.

twilio token:video --identity=<identity>

You can find examples of how to generate an Access Token for a participant using Twilio's Helper Libraries in the User Identity and Access Token guide.


Call connect to connect to a Room from your web application. Once connected, you can send and receive audio and video streams with other Participants who are connected to the Room.

1
const { connect } = require('twilio-video');
2
3
connect('$TOKEN', { name:'my-new-room' }).then(room => {
4
console.log(`Successfully joined a Room: ${room}`);
5
room.on('participantConnected', participant => {
6
console.log(`A remote Participant connected: ${participant}`);
7
});
8
}, error => {
9
console.error(`Unable to connect to Room: ${error.message}`);
10
});

You must pass the Access Token when connecting to a Room. You may also optionally pass the following:

  • Audio and video options , which when enabled will create and publish audio and video tracks from your local camera and microphone to the Room immediately upon connecting.
  • Local audio, data, and/or video tracks , to begin sharing pre-created local media and data with other Participants in the Room upon connecting.
  • A Room name , which allows you to dynamically specify the name of the Room you wish to join. (Note: You can also encode the Room name in the Access Token, which will allow the user to connect to only the Room specified in the token.)
  • A log level for debugging.

The name of the Room specifies which Room you wish to join. If you have enabled client-side Room creation for your Account and a Room by that name doesn't already exist, it will be created upon connection. If a Room by that name is already active, you'll be connected to the Room and receive notifications from any other Participants also connected to the same Room. Room names must be unique within an Account.

(information)

Default Room settings

If you have enabled client-side Room creation, or ad hoc Room creation, any new Room you create via the JavaScript SDK will follow the default Room settings that you've specified in your Account. These settings include options like a StatusCallback URL where you can receive Room creation and other webhook events, the maximum number of Participants, automatic recording, and more. You can view and update your default Room settings in the Twilio Console(link takes you to an external page).

You can also create a Room using the Rooms REST API. Look at the REST API Rooms resource docs for more details.


If you'd like to join a Room you know already exists, you handle that the same way as creating a Room: pass the Room name to the connect method.

Once in a Room, you'll receive a participantConnected event for each Participant that successfully joins. Querying the participants getter will return any existing Participants who have already joined the Room.

1
const { connect } = require('twilio-video');
2
3
connect('$TOKEN', { name: 'existing-room' }).then(room => {
4
console.log(`Successfully joined a Room: ${room}`);
5
room.on('participantConnected', participant => {
6
console.log(`A remote Participant connected: ${participant}`);
7
});
8
}, error => {
9
console.error(`Unable to connect to Room: ${error.message}`);
10
});

You can capture local media from your device's microphone, camera, or screen-share on different platforms in the following ways:

1
const { connect, createLocalTracks } = require('twilio-video');
2
3
// Option 1
4
createLocalTracks({
5
audio: true,
6
video: { width: 640 }
7
}).then(localTracks => {
8
return connect('$TOKEN', {
9
name: 'my-room-name',
10
tracks: localTracks
11
});
12
}).then(room => {
13
console.log(`Connected to Room: ${room.name}`);
14
});
15
16
// Option 2
17
connect('$TOKEN', {
18
audio: true,
19
name: 'my-room-name',
20
video: { width: 640 }
21
}).then(room => {
22
console.log(`Connected to Room: ${room.name}`);
23
});
(warning)

Warning

Tracks that are published through ConnectOptions will not emit trackPublished events for other Participants in the Room.

Use Twilio's createLocalTracks API(link takes you to an external page) to gain access to the user's microphone and camera. Note that some browsers, such as Google Chrome, will only let your application access local media when your site is served from localhost or over HTTPS.


Working with Remote Participants

working-with-remote-participants page anchor

Handle Connected Participants

handle-connected-participants page anchor

When you join a Room, Participants may already be present. You can check for existing Participants by using the Room's participants collection:

1
// Log your Client's LocalParticipant in the Room
2
const localParticipant = room.localParticipant;
3
console.log(`Connected to the Room as LocalParticipant "${localParticipant.identity}"`);
4
5
// Log any Participants already connected to the Room
6
room.participants.forEach(participant => {
7
console.log(`Participant "${participant.identity}" is connected to the Room`);
8
});
9
10
// Log new Participants as they connect to the Room
11
room.once('participantConnected', participant => {
12
console.log(`Participant "${participant.identity}" has connected to the Room`);
13
});
14
15
// Log Participants as they disconnect from the Room
16
room.once('participantDisconnected', participant => {
17
console.log(`Participant "${participant.identity}" has disconnected from the Room`);
18
});

Handle Participant Connection Events

handle-participant-connection-events page anchor

When Participants connect to or disconnect from a Room that you're connected to, you'll be notified via Participant connection events:

1
room.on('participantConnected', participant => {
2
console.log(`Participant connected: ${participant.identity}`);
3
});
4
5
room.on('participantDisconnected', participant => {
6
console.log(`Participant disconnected: ${participant.identity}`);
7
});

Display a Remote Participant's Video

display-a-remote-participants-video page anchor

To see the Video Tracks being sent by remote Participants, we need to render them to the screen. Because Participants can publish Tracks at any time, we'll want to handle both

  • the Tracks that the Participant has already published, and
  • the Tracks that the Participant eventually publishes.

We can handle the former by iterating over tracks and we can handle the latter by attaching an event listener for "trackSubscribed":

1
// Attach the Participant's Media to a <div> element.
2
room.on('participantConnected', participant => {
3
console.log(`Participant "${participant.identity}" connected`);
4
5
participant.tracks.forEach(publication => {
6
if (publication.isSubscribed) {
7
const track = publication.track;
8
document.getElementById('remote-media-div').appendChild(track.attach());
9
}
10
});
11
12
participant.on('trackSubscribed', track => {
13
document.getElementById('remote-media-div').appendChild(track.attach());
14
});
15
});

For RemoteParticipants that are already in the Room, we can attach their RemoteTracks by iterating over the Room's participants:

1
room.participants.forEach(participant => {
2
participant.tracks.forEach(publication => {
3
if (publication.track) {
4
document.getElementById('remote-media-div').appendChild(publication.track.attach());
5
}
6
});
7
8
participant.on('trackSubscribed', track => {
9
document.getElementById('remote-media-div').appendChild(track.attach());
10
});
11
});

Mute and Unmute Audio and Video

mute-and-unmute-audio-and-video page anchor

You can mute your LocalAudioTracks (microphone) and LocalVideoTracks (camera) by calling the disable method as shown below:

1
room.localParticipant.audioTracks.forEach(publication => {
2
publication.track.disable();
3
});
4
5
room.localParticipant.videoTracks.forEach(publication => {
6
publication.track.disable();
7
});

NOTE: Although disabling a LocalVideoTrack whose source is a camera stops sending media, the camera is still reserved by the LocalVideoTrack and hence its light still stays on. In some use cases, the desired behavior might be that the light should turn off when users mutes their camera. Although this method is not recommend, this can be achieved by calling stop on the LocalVideoTrack and unpublishing it from the Room:

1
room.localParticipant.videoTracks.forEach(publication => {
2
publication.track.stop();
3
publication.unpublish();
4
});

Handle Remote Media Mute Events

handle-remote-media-mute-events page anchor

When RemoteParticipants mute their media, you will be notified through a "disabled" event on the corresponding RemoteAudioTrack and/or RemoteVideoTrack. You can listen to this event as shown below:

1
function handleTrackDisabled(track) {
2
track.on('disabled', () => {
3
/* Hide the associated <video> element and show an avatar image. */
4
});
5
}
6
7
room.participants.forEach(participant => {
8
participant.tracks.forEach(publication => {
9
if (publication.isSubscribed) {
10
handleTrackDisabled(publication.track);
11
}
12
publication.on('subscribed', handleTrackDisabled);
13
});
14
});

NOTE: If RemoteParticipants mute their video by unpublishing their LocalVideoTracks, then you can listen to the "unsubscribed" event on the RemoteTrackPublication instead:

1
room.participants.forEach(participant => {
2
participant.tracks.forEach(publication => {
3
publication.on('unsubscribed', () => {
4
/* Hide the associated <video> element and show an avatar image. */
5
});
6
});
7
});

You can unmute your LocalAudioTracks and LocalVideoTracks by calling the enable method as shown below:

1
room.localParticipant.audioTracks.forEach(publication => {
2
publication.track.enable();
3
});
4
5
room.localParticipant.videoTracks.forEach(publication => {
6
publication.track.enable();
7
});

NOTE: If you muted your camera by stopping and unpublishing the associated LocalVideoTrack, then you can unmute your local video by creating a new LocalVideoTrack and publishing it to the Room:

1
const { createLocalVideoTrack } = require('twilio-video');
2
3
createLocalVideoTrack().then(localVideoTrack => {
4
return room.localParticipant.publishTrack(localVideoTrack);
5
}).then(publication => {
6
console.log('Successfully unmuted your video:', publication);
7
});

Handle Remote Media Unmute Events

handle-remote-media-unmute-events page anchor

When RemoteParticipants unmute their media, you will be notified through an "enabled" event on the corresponding RemoteAudioTrack and/or RemoteVideoTrack. You can listen to this event as shown below:

1
function handleTrackEnabled(track) {
2
track.on('enabled', () => {
3
/* Hide the avatar image and show the associated <video> element. */
4
});
5
}
6
7
room.participants.forEach(participant => {
8
participant.tracks.forEach(publication => {
9
if (publication.isSubscribed) {
10
handleTrackEnabled(publication.track);
11
}
12
publication.on('subscribed', handleTrackEnabled);
13
});
14
});

NOTE: If RemoteParticipants unmute their video by publishing new LocalVideoTracks, then you can listen to the "subscribed" event on the RemoteTrackPublication instead:

1
room.participants.forEach(participant => {
2
participant.tracks.forEach(publication => {
3
publication.on('subscribed', () => {
4
/* Hide the avatar image and show the associated <video> element. */
5
});
6
});
7
});

Display a Camera Preview

display-a-camera-preview page anchor

Sometimes you need to make sure you're looking fantastic before entering a Room. We get it. Each SDK provides a means to render a local camera preview outside the context of an active Room:

1
const { createLocalVideoTrack } = require('twilio-video');
2
3
createLocalVideoTrack().then(track => {
4
const localMediaContainer = document.getElementById('local-media');
5
localMediaContainer.appendChild(track.attach());
6
});

You can disconnect from a Room you're currently participating in. Other Participants will receive a "participantDisconnected" event:

1
room.on('disconnected', room => {
2
// Detach the local media elements
3
room.localParticipant.tracks.forEach(publication => {
4
const attachedElements = publication.track.detach();
5
attachedElements.forEach(element => element.remove());
6
});
7
});
8
9
// To disconnect from a Room
10
room.disconnect();

The Programmable Video REST API allows you to control your video applications from your back-end server via HTTP requests.

Need some help?

Terms of service

Copyright © 2024 Twilio Inc.