This tutorial will walk you through the steps of setting up a basic client for a Vonage Video API web app.
All applications that use the Vonage Video API require both a client and a server component. The client-side code is what loads in an end-user's browser and handles the majority of OpenTok functionality, including connecting to the session, publishing audio-video streams to the session, and subscribing to other clients’ streams. For more information on clients, servers, and sessions, see Video API Basics.
In this tutorial, you will be utilizing OpenTok.js, OpenTok's client-side library for the web, to quickly and easily build a real-time interactive video application.
Estimated completion time: 20 mins
Want to skip this tutorial? You can jump to the completed web client code in the Basic Video Chat folder of our Web sample app repo on GitHub. The repo includes a README with documentation for running and exploring the code.
To complete this tutorial, you'll need:
For this project, you will be creating an HTML file, a JavaScript file, and a CSS file.
Before you get started with code, go ahead and create a new project folder on your computer to house these files (the example below is called myproject but you can name it whatever you like). Then add a /js and /css folder along with blank files for index.html, app.js, and app.css in the following structure:
/myproject
/js
app.js
/css
app.css
index.html
Once you have your project set up, open the main project folder in your code editor and go to the index.html file.
Copy the following code (using the copy button) and add it to your index.html file in the code editor:
<html>
<head>
<title> OpenTok Getting Started </title>
<link href="css/app.css" rel="stylesheet" type="text/css">
<script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
</head>
<body>
<div id="videos">
<div id="subscriber"></div>
<div id="publisher"></div>
</div>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
The above code includes references to the OpenTok.js library as well as the JS and CSS files you just created. The code also includes publisher and subscriber divs, which will contain the video streams — we'll use these classes to customize the layout later.
This sample loads OpenTok.js directly from static.opentok.com. OpenTok.js is also available as a NPM package. For instructions on using the NPM package, see https://www.npmjs.com/package/@opentok/client.
Pull up your blank app.js file in your code editor — most of the remaining steps will involve adding code to this file.
In order to connect to an OpenTok session, the client will need access to some authentication credentials — an API Key, Session ID, and Token. In a production application, these credentials should be generated by a server, but to speed things up we will just hard code the values for now.
Start by copying the following code block and adding it to your app.js file:
// replace these values with those generated in your Video API account
var apiKey = "YOUR_API_KEY";
var sessionId = "YOUR_SESSION_ID";
var token = "YOUR_TOKEN";
// (optional) add server code here
initializeSession();
You'll need to adjust the code above by hard coding the values for the apiKey
, sessionId
and token
. To do this, log into your Video API account, either create a new OpenTok API project or use an existing OpenTok API project, then go to your project page and scroll down to the Project Tools section — from there, you can generate a Session ID and Token manually. Use the project's API Key along with the Session ID and Token you generated to replace YOUR_API_KEY
, YOUR_SESSION_ID
and YOUR_TOKEN
in the code above (be sure to leave the quotation marks.)
Important: You can continue to get the session ID and token values from your Account during testing and development, but before you go into production you must set up a server. See the optional guide for setting up a server at the end of this tutorial.
For more information on sessions, tokens, and servers, check out Video API Basics.
You may have noticed the initializeSession()
method being called in the last step after getting the session ID and token. This method initializes a session object and then connects to the session, but we haven't defined it in our code yet.
Copy the following code and paste it below the existing code in your app.js file:
// Handling all of our errors here by alerting them
function handleError(error) {
if (error) {
alert(error.message);
}
}
function initializeSession() {
var session = OT.initSession(apiKey, sessionId);
// Subscribe to a newly created stream
// Create a publisher
var publisher = OT.initPublisher('publisher', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
// Connect to the session
session.connect(token, function(error) {
// If the connection is successful, publish to the session
if (error) {
handleError(error);
} else {
session.publish(publisher, handleError);
}
});
}
Creating a publisher
The application initializes an OpenTok publisher
object with OT.initPublisher()
. This method takes three optional parameters:
publisher
divinsertMode
, height
, and width
attributesRead more about these options in the OT.initPublisher() reference documentation.
Initializing and connecting to the session
The OT.initSession()
method takes two parameters — the OpenTok API key and the session ID. It initializes and returns an OpenTok session
object.
The connect()
method of the session
object connects the client application to the OpenTok session. You must connect before sending or receiving audio-video streams in the session (or before interacting with the session in any way). The connect()
method takes two parameters — a token
and a completion handler function function(error)
.
Once the session is connected, we publish to the session with session.publish(publisher)
.
If the client fails to connect to the OpenTok session, an error object is passed into the completion handler of the connect event — in this case it prints an error message to the console using console.error()
.
Finally, we want clients to be able to subscribe to (or view) each other's streams in the session.
In your current app.js file, you should have a comment that says // Subscribe to a newly created stream
. Copy the following code and add it directly under that comment:
session.on('streamCreated', function(event) {
session.subscribe(event.stream, 'subscriber', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
});
When a new stream is created in the session, the Session object dispatches a streamCreated
event. When the client detects a stream, we want it to subscribe to that stream, and we do this in the code above with the session.subscribe()
method. This method takes four parameters:
event.stream
subscriber
divinsertMode
, height
, and width
attributessubscribe()
method completes successfully or failsRead more about these options in the Session.subscribe() reference documentation.
At this point, your app.js file should look something like this (with a few adjustments):
// replace these values with those generated in your Video API account
var apiKey = "YOUR_API_KEY";
var sessionId = "YOUR_SESSION_ID";
var token = "YOUR_TOKEN";
// Handling all of our errors here by alerting them
function handleError(error) {
if (error) {
alert(error.message);
}
}
// (optional) add server code here
initializeSession();
function initializeSession() {
var session = OT.initSession(apiKey, sessionId);
// Subscribe to a newly created stream
session.on('streamCreated', function(event) {
session.subscribe(event.stream, 'subscriber', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
});
// Create a publisher
var publisher = OT.initPublisher('publisher', {
insertMode: 'append',
width: '100%',
height: '100%'
}, handleError);
// Connect to the session
session.connect(token, function(error) {
// If the connection is successful, initialize a publisher and publish to the session
if (error) {
handleError(error);
} else {
session.publish(publisher, handleError);
}
});
}
In your completed code, you should have hard coded values to replace YOUR_API_KEY
, YOUR_SESSION_ID
and YOUR_TOKEN
— if you haven't done this, see Setting up authentication above.
If everything checks out, go ahead and test your code by loading the index.html file in Chrome or Firefox.
When you load the page, you may need to allow the browser to access your webcam and microphone. After that, you should see a video stream of yourself (or whatever your webcam is looking at) displaying on the page.
If that worked, mute your audio then open another tab (keeping the original open) and load the same URL. You should now be able to scroll down and see a second video. If you right-click on either video and "Inspect Element", you should see that one of the videos is filling the subscriber
div, and the other is filling the publisher
div.
Troubleshooting tip: If there's no video showing up on the page, open the "console" tab in your browser tools (command+option+i on Mac, CTRL+i on Windows) and check for errors. The most likely issue is that your API key, session ID, or token is not set up properly. Since you hard coded your credentials, it's also possible that your token has expired.
At this point, you have a complete working client using OpenTok. This last step will just demonstrate some basic CSS customization to produce a "picture-in-picture" layout.
Open up your blank app.css file in your code editor and add the following code to it:
body, html {
background-color: gray;
height: 100%;
}
#videos {
position: relative;
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
#subscriber {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
#publisher {
position: absolute;
width: 360px;
height: 240px;
bottom: 10px;
left: 10px;
z-index: 100;
border: 3px solid white;
border-radius: 3px;
}
Once you've saved the CSS, reopen your index in two separate browser tabs again — you should now see two video streams, but one will be smaller and nested inside the larger video stream.
Taking a look at the CSS above, you can see that we did this by adjusting the height, width, and position of the #publisher
div. This "picture-in-picture" layout is a common practice in video chats, but feel free to adjust the CSS to play with the sizing and position of these divs as much as you like.
Congratulations! You've finished the 'Set up a Basic Web Client' tutorial.
You can continue to play with and adjust the code you've developed here for the client-side of your application, but keep in mind that you'll need to implement the server component of your application before going to production (see Setting up your server below).
When you're finished here, continue building and enhancing your OpenTok application with these helpful resources:
In the tutorial above, we had you hard code your authentication credentials. However, for a production application, the sessionId
and token
values in your code must be generated by your app server and passed to the client. Here are a couple of reasons why you don't want hard coded credentials in your production app:
You can continue testing your application with hard coded values, but when you're ready to set up a server there are a number of ways to do so:
This is probably the fastest way to get a server up and running, but it has limited functionality. Simply click the Heroku button below, at which point you'll be sent to Heroku's website and prompted for your OpenTok API Key and API Secret — you can get these values on your project page in your Video API account. If you don't have a Heroku account, you'll need to sign up (it's free).
Want to explore the code? The button above launches server code from the learning-opentok-php GitHub repo. Visit the repo to review the code as well as additional documentation — you can even fork the repo and make changes before deploying.
Prefer Node.js? Visit the learning-opentok-node repo for the same functionality using Node.js (including Heroku deploy button.)
Once the server is deployed on Heroku (either PHP or Node.js), you'll need to add a few lines to your client-side code. In your app.js file, you should see a comment // (optional) add server code here
.
Copy the following code and use it to replace // (optional) add server code here
and the initializeSession()
call in your app.js file:
// (optional) add server code here
var SERVER_BASE_URL = 'https://YOURAPPNAME.herokuapp.com';
fetch(SERVER_BASE_URL + '/session').then(function(res) {
return res.json()
}).then(function(res) {
apiKey = res.apiKey;
sessionId = res.sessionId;
token = res.token;
initializeSession();
}).catch(handleError);
You'll need to replace https://YOURAPPNAME.herokuapp.com
with your actual Heroku app url — you can find this on your app page on the Heroku website.
The code above uses Ajax to make a request to the /session endpoint (https://YOURAPPNAME.herokuapp.com/session), which should return an HTTP response that includes the session ID, the token, and API key formatted as JSON data, which is then assigned to the corresponding variables.
This /session
endpoint will always return the same session ID, but will produce a new token each time it's called — this results in each client receiving a unique token.
Option 1 uses REST endpoints for transmitting credentials to the client, but that's only one of many ways to implement a server with OpenTok. If you want a greater level of customization, you can review OpenTok's Server SDK documentation for the server-side language of your choice (available for PHP, Node.js, Java, .NET, Python and Ruby). The documentation goes over the setup process and the various methods you'll need to generate sessions and tokens, as well as other server-side functionality.
We've developed basic sample apps with completed client-server code for each server-side language (PHP, Node.js, Java, .NET, Python, and Ruby.) These include completed clients, so you will not need the client code you set up in this tutorial.
To view the sample apps for your preferred language, go to our Code Samples page and select one of the server-side languages under Simple client-server for web.