This blog post provides a tutorial on building a video conferencing application using WebRTC. Instead of complicating things, we’ll show you how to create a simple one-to-one video conferencing application using WebRTC APIs and a few other libraries to build a custom signaling server.
Before we get started, let’s look at the following diagram of the WebRTC communication process:
The process for enabling communication on WebRTC can be seen as a three-step flow:
- The browser receives access to the media devices (the camera and the microphone).
- Each peer exchanges information about itself with other peers through a signaling process.
- After signaling, peers connect directly and communication begins.
To make all of this possible, a signaling server is necessary for information exchange. Additionally, a pair of STUN/TURN servers are required to achieve NAT traversal and relay media if direct communication is not possible.
Without further ado, let’s dive into the application!
Now we will build a simple one-to-one video conference application. It will have a “rooms” functionality, where each “room” will host a different call.
The first thing a user will see is a screen to type a room number. The room number can be anything the users wants it to be. When another user wants to join the first user, they need to enter that room number for the call to begin.
Let’s begin by creating a folder anywhere you want. This will be our project folder. Then create another one inside called public. Using the command line, navigate to the project folder and paste the following commands to install the required dependencies. An internet connection is required to download the libraries.
npm init -y
npm install -S email@example.com firstname.lastname@example.org
Now let’s create a simple HTML file. It will contain two div elements, one for typing the room number and another for showing the video streams. The file will also contain script tags for the socket.io client library and another file that we will create later.
Using your favorite text editor, create a new file, paste the following code, and save it in your project folder, inside public as index.html.
We’re also going to connect to socket.io server and add a click event to the button in which we’ll send a ‘create or join’ message to the server. Paste the following code in a new file and save it as client.js. in the public folder.
We need to wait for the responses after sending the initial message to the server, so we’re going to set up some event handlers in the same client.js file.
When the first participant joins the call, the server creates a new room and emits a ‘joined’ event to them. The same process is repeated on the second participant’s side: The browser receives access to the media devices, stores the stream on a variable and shows the video on the screen. Another action is taking place, too: A ‘ready’ message is sent to the server. Add the following code to the bottom of the client.js file.
Up until now, the first step is done. The server receives the ‘ready’ message and notifies the first participant by sending him the same message. This begins the exchange of information process known as Signaling. We need to add the correspondent handlers to our client.js file.
When the first participant receives the ‘ready’ message, its callback creates an RTCPeerConnection object and sets the object’s onicecandidate and onaddstream listeners to the onIceCandidate and onAddStream functions, respectively. Se will review these functions later. Finally., it adds the local stream to the peer connection object. After that, it prepares an Offer, which will be stored locally and then sent to the server by the setLocalAndOffer function.
The server relays the offer to the second participant, which in turn completes the same process on the ‘offer’ callback: It creates its own peer connection object, sets its event listeners, stores the offer, and prepares an Answer that will be stored locally and then sent to the server by the setLocalAndAnswer function.
Similar to the offer, the server will relay the answer to the first participant who will store it. While all of this is happening, both peers are exchanging ice candidates by sending ‘candidate’ messages to the server, which in turn relays them to the other client. The ice candidates are added to each client’s peer connection object. Add the following code to the bottom of the client.js file.
Now the second step is done. When everything is ready, each peer receives the remote stream, then the onAddStream function shows it on the screen. Below are the remaining functions of our client.js file.
Now our three-step flow is complete. But we still haven’t completed our server. Begin by requiring the needed libraries and setting static hosting on the public folder to serve the client files.
We will define the signaling handlers using socket.io. First, we’ll have the ‘create or join’ event, which will count the number of clients in the room. If there are no users in the room, this means that the client is the first peer, so a ‘created’ event is sent to them. If there is already one participant in the room, then the client is added to the room and a ‘joined’ event is sent to them. If there are already two participants in the room, then the room is considered full and no more clients are added.
The subsequent events work as relays only, sending the same message received to the other client in the room. Create a new file, paste the following code, and save it on the project folders as server.js.
Using Google Chrome or Mozilla Firefox, open this link in two separate tabs. Be sure to enter the same room number in both, then click Go.
We created our first video conference application! Cool, isn’t it?