Build a Video App with JavaScript and the Twilio CLI in 9 Minutes
Tags: twilio, javascript, video, html
Published: 2020-05-28 21:50:07

---
title: Build a Video App with JavaScript and the Twilio CLI in 9 Minutes
published: true
description: Demystify video! Learn how to quickly build and deploy a video app using JavaScript, Twilio Video, and the Twilio CLI.
tags: twilio, javascript, js, video, html
---
![video header](https://twilio-cms-prod.s3.amazonaws.com/images/KJ8Ew2VJoDmV54Cdch1d9LHF2gKBiBhCDsyCMwCUwtBKv.width-1616.png)

This blog post was written for [Twilio](https://www.twilio.com/) and [originally published on the Twilio blog](https://www.twilio.com/blog/build-a-video-app-javascript-twilio-cli-quickly).

With many of us now working remote, video chats are so in right now. Here’s how to get up-and-running with a video chat room in nine minutes using [Twilio Programmable Video](https://www.twilio.com/docs/video/javascript) and the [Twilio Serverless Toolkit](https://www.twilio.com/docs/labs/serverless-toolkit) in JavaScript.
![example img](https://twilio-cms-prod.s3.amazonaws.com/images/kzfah5yLkhJBqUXLQXB-_wXlYTE1KYI8od19cXGW3GOZv.width-1000.jpg)

## Setup
To build a Twilio Programmable Video application, we will need:
- A Twilio account - [sign up for a free one here and receive an extra $10 if you upgrade through this link](http://www.twilio.com/referral/iHsJ5D)
- Account SID: find it in [your account console here](https://www.twilio.com/console)
- API Key SID and API Key Secret: [generate them here](https://www.twilio.com/console/runtime/api-keys)
- The [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart)

Save your API Keys somewhere you can access them soon and then [install the Twilio Serverless Toolkit](https://www.twilio.com/docs/labs/serverless-toolkit/getting-started#install-the-twilio-serverless-toolkit) via the Twilio CLI if you haven't already by running
```bash
twilio plugins:install @twilio-labs/plugin-serverless
```
You can then see what commands the Serverless Toolkit offers by running
```bash
twilio serverless
```

## Make a Serverless Project
Create a Serverless project with a blank template by running on the command line
```bash
twilio serverless:init --template blank {insert-project-name}
```
Replace `{insert-project-name}` with your project name--I called mine `tfvideo`. When the command completes, a directory with the project name will be created under your current directory.

The project directory contains some ready-made folders. In `functions`, add a file called `video-token.js` and in assets add two files: `video.html` and `index.js`. Set your environment variables in `.env`. You can leave the first two lines containing `ACCOUNT_SID` and `AUTH_TOKEN` alone. Below them, add your Account SID, API Key, and API Secret:
![env](https://twilio-cms-prod.s3.amazonaws.com/images/2ygV4LOF8M1iEFgWVzxcCp9KHu4YOpDs87r3-joickdu-.width-1000.png)

## Generate an Access Token
In `functions/video-token.js` add the following code to generate an access token. Here we set your environment variables, a fixed room name, and the `ACCESS_TOKEN_IDENTITY` for each user. Each user is granted access to the room `tf`. This code was modified from [this page which also contains more information on Access Tokens](https://www.twilio.com/docs/video/tutorials/user-identity-access-tokens).

```javascript
exports.handler = function(context, event, callback) {
    const TWILIO_ACCOUNT_SID = context.TWILIO_ACCOUNT_SID;
    const TWILIO_API_KEY = context.TWILIO_API_KEY;
    const TWILIO_API_SECRET = context.TWILIO_API_SECRET;
    const ACCESS_TOKEN_IDENTITY =
      Math.random()
        .toString(36)
        .substring(2, 15) +
      Math.random()
        .toString(36)
        .substring(2, 15);  // random client name 

    const ROOM_NAME = 'tf';  // fixed room name
    const AccessToken = Twilio.jwt.AccessToken;
    const VideoGrant = AccessToken.VideoGrant;
    // only tokens are available for participating rooms
    // Create a Video grant enabling client to use Video, only for this room 
    const videoGrant = new VideoGrant({
        room: ROOM_NAME
    });
    //Create an access token to sign and return to the client with the grant we just created
    const accessToken = new AccessToken(
        TWILIO_ACCOUNT_SID,
        TWILIO_API_KEY,
        TWILIO_API_SECRET
    );
    accessToken.addGrant(videoGrant); //Add the grant to the token
    accessToken.identity = ACCESS_TOKEN_IDENTITY;
    callback(null, {
        token: accessToken.toJwt() //Serialize the token to a JWT string
    });
};
```

## Make our Video Site
Now open the blank `assets/video.html` file you made earlier. We're going to write some bare-bones HTML including buttons for joining and leaving the room, a video tag that will automatically display a preview of the user's camera, the `index.js` file we're about to write, and the Axios and Twilio Video.js libraries:
```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Twilio Video Serverless Demo</title>
</head>
  <body>
    <div id="room-controls">
      <video id="video" autoplay muted="true" width="320"
          height="240"></video>
      <button id="button-join">Join Room</button>
      <button id="button-leave" disabled>Leave Room</button>
    </div>

  <script src="//media.twiliocdn.com/sdk/js/video/releases/2.3.0/twilio-video.min.js"></script>
  <script src="https://unpkg.com/axios@0.19.0/dist/axios.min.js"></script>
  <script src="index.js"></script>
  </body>
</html>
```

## Build the Video App
In `assets/index.js` add the following code. In a nutshell, this copy-and-pasteable script will:
- set the serverless domain name (this will be the base URL) as whatever you called your project with the CLI template
- set the name of your room name, and some variables
- get the video element and display it in the preview screen
- generate an access token using an `axio`s call to the `video-token` file when a user joins the room
- connect and disconnect users to the `tf` room when they click `button-join` or `button-leave`
- display a remote participant's video by attaching an event listener to subscribe or unsubscribe their tracks to the `tf` room. If they are already in the room, we iterate over the existing `participants` and attach an event listener to `trackSubscribed`.

If you change the room name, you must also change the token that's generated.
```javascript
(() => {
    'use strict';
    const TWILIO_DOMAIN = location.host; //unique to user, will be website to visit for video app
    const ROOM_NAME = 'tf';
    const Video = Twilio.Video;
    let videoRoom, localStream;
    const video = document.getElementById("video");
   
    // preview screen
    navigator.mediaDevices.getUserMedia({video: true, audio: true})
    .then(vid => {
        video.srcObject = vid;
        localStream = vid;
    })
        
    // buttons
    const joinRoomButton = document.getElementById("button-join");
    const leaveRoomButton = document.getElementById("button-leave");
    var site = `https://${TWILIO_DOMAIN}/video-token`;
    console.log(`site ${site}`);
    joinRoomButton.onclick = () => {
      // get access token
      axios.get(`https://${TWILIO_DOMAIN}/video-token`).then(async (body) => {
        const token = body.data.token;
        console.log(token);

        Video.connect(token, { name: ROOM_NAME }).then((room) => {
          console.log(`Connected to Room ${room.name}`);
          videoRoom = room;

          room.participants.forEach(participantConnected);
          room.on("participantConnected", participantConnected);

          room.on("participantDisconnected", participantDisconnected);
          room.once("disconnected", (error) =>
            room.participants.forEach(participantDisconnected)
          );
          joinRoomButton.disabled = true;
          leaveRoomButton.disabled = false;
        });
      });
    };
    leaveRoomButton.onclick = () => {
      videoRoom.disconnect();
      console.log(`Disconnected from Room ${videoRoom.name}`);
      joinRoomButton.disabled = false;
      leaveRoomButton.disabled = true;
    };
})();

const participantConnected = (participant) => {
    console.log(`Participant ${participant.identity} connected'`);

    const div = document.createElement('div');
    div.id = participant.sid;

    participant.on('trackSubscribed', track => trackSubscribed(div, track));
    participant.on('trackUnsubscribed', trackUnsubscribed);
  
    participant.tracks.forEach(publication => {
      if (publication.isSubscribed) {
        trackSubscribed(div, publication.track);
      }
    });
    document.body.appendChild(div);
}

const participantDisconnected = (participant) => {
    console.log(`Participant ${participant.identity} disconnected.`);
    document.getElementById(participant.sid).remove();
}

const trackSubscribed = (div, track) => {
    div.appendChild(track.attach());
}

const trackUnsubscribed = (track) => {
    track.detach().forEach(element => element.remove());
}
```
Yes, this has been Programmable Video demystified and simplified!

On the command line, run `twilio serverless:deploy`. The CLI will congratulate you with <em>Serverless project successfully deployed</em> and some other deployment details. You can delete or ignore `functions/blank.js` which was deployed with the auto-generated assets. Grab the `video.html` URL under `Assets`, share it with your friends, and <em>tada</em>! You have your own video room to use and share when you need a quick video call.
![larger group call with Mica, Tilde](https://twilio-cms-prod.s3.amazonaws.com/images/iw-DP-6CcG8xIK-Ln2SaidRDsCuII0EXrpXcfQyJpuQs-.width-1000.png)

This app is pretty bare-bones but definitely decent given the lack of CSS written, eh? The complete code can be [found here on GitHub](https://github.com/elizabethsiegle/twilioVideoWebChat9Mins).

## What's Next
Twilio's Serverless Toolkit makes it easy to host apps and get them up-and-running quickly. Next you can write some more CSS to prettify the app, add a [programmable chat feature](https://www.twilio.com/docs/chat) or [more Twilio Video features](https://www.twilio.com/docs/video/javascript-v2-getting-started), get users' names and display them when they are in the chat, and more. Let me know online or in the comments what you're building.

- Twitter: [@lizziepika](https://twitter.com/lizziepika
- GitHub: [elizabethsiegle](https://github.com/elizabethsiegle)
- email: lsiegle@twilio.com