You are on page 1of 32

8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

You have 2 free stories left this month. Sign up and get an extra one for free.

WebRTC Video Chat App Development


Suminda Niroshan Follow
Oct 12, 2019 · 11 min read

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 1/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

Y ou have probably used Skype, WhatsApp, Viber and tons of other video chat
applications. Did you know that it’s possible to develop a similar kind of video
chat web application with just HTML and pure JavaScript using an in-built technology
in browsers? That technology is called WebRTC.

Prerequisites
You need to have an AWS account and some basic knowledge working with AWS services
and how to deploy with Serverless Framework. Following AWS services will be utilised
throughout this guide.

Lambda Service

AWS EC2 Instance (Will be created and configured manually)

AWS Websockets

AWS DynamoDB

AWS S3

Make sure to have the following installed,

Node 6.0 or later

AWS CLI Configured for your account

We’ll be using Serverless Framework to configure and deploy the whole infrastructure
needed. So we don’t need to go to AWS console and create resources manually (Except
for the EC2 instance). Please refer to this blog post if you need help on setting
Serverless Framework up.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 2/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

Since
We’ve AWS
made Websockets
changes are of
to our Terms also being
Service andused,
PrivacyI recommend reading
Policy. They take e ect onthis blog post
September asand
1, 2020, wellwe
encourage
to get a you to review
better them. By continuing
understanding of AWStoWebsocket
use our services,
basicyou agree to
usage. the new
This Termsisofbuilt
project Service
onand
acknowledge the Privacy Policy applies to you.
top of that project.
Continue

You will learn


How to leverage WebRTC with other required mechanisms and components to build a
Video chat application in a web application.

. . .

WebRTC (Web Real Time Communication)


WebRTC (Web Real-Time Communication) is a free, open-source project that provides web
browsers and mobile applications with real-time communication (RTC) via simple
application programming interfaces (APIs). It allows audio and video communication to
work inside web pages by allowing direct peer-to-peer communication, eliminating the need
to install plugins or download native apps.

This communication is extremely fast with low latency as the connection is peer to
peer and there’s no server in the middle. This technology is developed by Google and
currently almost all browsers support it except in iOS platform (Only Safari supports).
Different API methods are supported in different browsers which can make the
development of these applications difficult. Hopefully these differences fade away over
time. You can find API methods and their browser support in this link.

Why Do We Need It
If we want two browsers running in two different parts of the world to connect and
exchange real time video chat streams, we need a TCP or UDP connection like below.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 3/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

WebRTC helps us achieve this connection.

How Does It Work


Usually our PCs, Laptops or mobiles exists in a local area network behind a NAT, a
Router and a firewall. In order to make a direct connection with browser to browser, we
need to deal with all of these.

Having these layers between browsers that try to make a direct peer to peer connection
makes it impossible to connect without the involvement of signalling mechanisms.

In order to deal with these, following components are needed,

A Signalling Mechanism

STUN Server

TURN Server

Interactive Connectivity Establishment (ICE)

Signalling Process

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 4/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

Let’smade
We’ve havechanges
a looktoatour
these.
Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
SignallingtheMechanism
acknowledge Privacy Policy applies to you.

Continue
Before starting video and audio streaming between two browsers, we need to establish
who is participating. In order to do this, both parties needs to be able to exchange
metadata before attempting to stream. Websockets are the most used for this. In this
demo, AWS Websockets will be used.

Once this socket connection is established, it will be used to send back and forth the data
needed to create a peer to peer connection.

ICE (Interactive Connectivity Establishment)


This is a coordination standard for Stun and Turn servers to establish a direct
communication between peers. Multiple ICE candidates are generated during the initial
signalling process for connection establishment and peers will pick the one that
succeeds.

STUN (Session Traversal Utilities for NAT) Server


This is a server that enables a peer to find it’s public IP address. When a peer wants to
connect to another host, it will provide this public IP address as a potential connectivity
endpoint. If the existing NAT between the two peers allows for a direct connection
between the two hosts, then a direct peer to peer connection will be made using an ICE
(Interactive Connectivity Establishment).

In this case, a Turn server is not needed. If the Stun server fails to provide a working ICE,
WebRTC will then attempt with the Turn server.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 5/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

TURN (Traversal Using Relay around NAT) Server


As the name implies, this server relays media between the hosts that are connected to it
using an ICE. When you want to make a call between different networks or when NAT
won’t allow direct access to a host, this is the way to go. Turn server acts as a relay
between peers so the peers doesn’t need to find ways through their NATs. Turn server
has a public facing IP address which peers can connect to.

The good thing is, we don’t have to worry about this (When to use Stun or Turn) as the
evaluation and connection establishment is done automatically for us by WebRTC
engine.

But, we do need to create and host our own Stun/Turn server (We’ll do that in a further
section).

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 6/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.
Signalling Process
Continue
Once the web socket connection is in place, following is the process that goes onto
establishing a peer to peer connection.

[1]. Caller and Receiver connects to each other via a Websocket connection.
[2]. Caller creates an Offer.
[3]. Caller sends the Offer to the Receiver via the Websocket connection.
[4]. Caller receives ICE candidates from the Stun/Turn server.
[5]. Caller sends all ICE candidates to the Receiver via the Websocket connection.
[6]. Receiver accepts the Offer.
[7]. Receiver accepts the ICE candidates sent from the Caller.
[8]. Receiver creates an Answer.
[9]. Receiver sends the Answer to the Caller via the Websocket connection.
[10]. Caller accepts the Answer.
[11]. Receiver tests the ICE candidates sent from the Caller and picks the one that is
successful in making a connection.
[12]. A peer to peer connection is established between the Caller and the Receiver
through an ICE connection

Demo Chat Application Build


Before we dive into the application build let’s break down the components and how we
implement each of them. You can find the Github Repo from this link.

1. Client Application
This will be implemented just using a simple HTML page and pure JavaScript. No
JavaScript libraries. Not even WebRTC helper libraries are used. I want to keep
things simple, under control and not get lost in a framework hell.

2. Signalling Mechanism (Web sockets)


As mentioned before, AWS Websockets will be used. This is the same mechanism
used to develop a simple chat application as shown in this blog post which I have
explained in detail.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 7/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

3. made
We’ve Stun/Turn
changesServer
to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review
We will be using them.
the By continuing
most popular to use our services,
Stun/Turn you agree
server opentosource
the newproject
Terms ofcalled
Service and
acknowledge the Privacy Policy applies to you.
Coturn. This will be hosted in an Ubuntu AWS EC2 instance.
Continue
4. Project Deployment
Serverless Framework will be used to deploy the infrastructure (Websocket server)
that is needed into AWS. If you don’t know how this works, take a look at this blog
post.

1. Deploying The AWS Websocket


This project contains a Serverless Framework project configuration for an AWS
Websocket which transmits received messages to all connected clients.

1. Get the source code from this Github Repo and go in to the project directory from
your CLI.

2. Install required npm packages first.


$ npm install

3. Install Serverless Framework globally.


$ npm install -g serverless

4. Deploy into AWS


$ serverless deploy --stage websocket

After the deployment, you should get the AWS Websocket endpoint as displayed below.
Copy this URL as it is needed for our web client application configuration.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 8/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

2. Hosting The Stun/Turn Server


We’ll be hosting this in an AWS EC2 Ubuntu virtual machine instance.

1. Go ahead and create an AWS EC2 instance with the following image (I have used
“ami-02df9ea15c1778c9c”). You can keep all the default settings.

2. Go to EC2 Security Group settings and open all in-bound UDP ports as displayed
below. This is required for the Stun/Turn server to function properly.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 9/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

3. SSH
We’ve into
made the EC2
changes to ourinstance and execute
Terms of Service the Policy.
and Privacy following commands.
They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge
a) Acquirethe Privacy
super Policy
user applies to you.
environment.
sudo -i Continue

b) Install required libraries.


apt-get update && apt-get install libssl-dev libevent-dev libhiredis-dev make -y

c) Install Coturn project.


apt install coturn

d) Exit from super user environment.


exit

e) Start the Coturn turn server.


turnserver -a -o -v -n -u USERNAME:PASSWORD -p 3478 -L EC2_Private_IP -r someRealm

-X EC2_Public_IP/EC2_Private_IP --no-dtls --no-tls

Make sure to replace USERNAME and PASSWORD with the ones you want.
Replace EC2_Public_IP and EC2_Private_IP with your EC2 instance’s IP addresses as
displayed below.

f) Verify Coturn is running by executing the following command as displayed below.


https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 10/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

netstat
We’ve -lnp | to
made changes grep 3478 of Service and Privacy Policy. They take e ect on September 1, 2020, and we
our Terms
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

3. The Client Application Build


Before deploying the client WebRTCChat.html file, let’s have a look at the code.

1 function connectToWebSocket(){
2 socket = new WebSocket(webSocketConnection);
3
4 // Create WebRTC connection only if the socket connection is successful.
5 socket.onopen = function(event) {
6 log('WebSocket Connection Open.');
7 createRTCPeerConnection();
8 };
9
10 // Handle messages recieved in socket
11 socket.onmessage = function(event) {
12 jsonData = JSON.parse(event.data);
13
14 switch (jsonData.type){
15 case 'candidate':
16 handleCandidate(jsonData.data, jsonData.id);
17 break;
18 case 'offer':
19 handleOffer(jsonData.data, jsonData.id);
20 break;
21 case 'answer':
22 handleAnswer(jsonData.data, jsonData.id);
23 break;
24 default:
25 break
26 }
27 };
28
29 socket.onerror = function(event) {
30 console.error(event);
31 log('WebSocket Connection Error Make sure web socket URL is correct and web
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 11/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
31 log( WebSocket Connection Error. Make sure web socket URL is correct and web
We’ve
32 made changes}; to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
33
you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.
34 socket.onclose = function(event) {
35 log('WebSocket ConnectionContinue
Closed. Please Reload the page.');
36 document.getElementById("sendOfferButton").disabled = true;
37 document.getElementById("answerButton").disabled = true;
38 };
39 }

Upon page load, user will be asked to give permission to access camera and microphone
using getUserMedia method. After access is given the above code is executed to establish
a web socket connection and setup event handlers to handle Offer/Answer and ICE
Candidates.

onmessage handler will handle received socket messages according to their type (ICE
Candidate, Answer or Offer).

onopen handler will setup a WebRTC Peer Connection once the web socket
connection is successful with createRTCPeerConnection method displayed below.

1 function createRTCPeerConnection(){
2 connection = new RTCPeerConnection(configuration);
3
4 // Add both video and audio tracks to the connection
5 for (const track of localStream.getTracks()) {
6 log("Sending Stream.")
7 existingTracks.push(connection.addTrack(track, localStream));
8 }
9
10 // This event handles displaying remote video and audio feed from the other peer
11 connection.ontrack = event => {
12 log("Recieved Stream.");
13 document.getElementById("remoteVideo").srcObject = event.streams[0];
14 }
15
16 // This event handles the received data channel from the other peer
17 connection.ondatachannel = function (event) {
18 log("Recieved a DataChannel.")
19 channel = event.channel;
20 setChannelEvents(channel);
21 document.getElementById("sendMessageButton").disabled = false;
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 12/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

22 };
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
23
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
24
acknowledge // This
the Privacy event
Policy sendstothe
applies you.ice candidates generated from Stun or Turn server to the
25 connection.onicecandidate = event => {
26 if (event.candidate) {
Continue
27 log("Sending Ice Candidate - " + event.candidate.candidate);
28
29 socket.send(JSON.stringify(
30 {
31 action: 'onMessage',
32 type: 'candidate',
33 data: event.candidate,
34 id: clientId
35 }
36 ));
37 }
38 }
39
40 // This event logs messages and handles button state according to WebRTC connect
41 connection.onconnectionstatechange = function(event) {
42 switch(connection.connectionState) {
43 case "connected":
44 log("Web RTC Peer Connection Connected.");
45 document.getElementById("answerButton").disabled = true;
46 document.getElementById("sendOfferButton").disabled = true;
47 document.getElementById("hangUpButton").disabled = false;
48 document.getElementById("sendMessageButton").disabled = false;
49 break;
50 case "disconnected":
51 log("Web RTC Peer Connection Disconnected. Please reload the page to
52 disableAllButtons();
53 break;
54 case "failed":
55 log("Web RTC Peer Connection Failed. Please reload the page to recon
56 console.log(event);
57 disableAllButtons();
58 break;
59 case "closed":
60 log("Web RTC Peer Connection Failed. Please reload the page to recon
61 disableAllButtons();
62 break;
63 default:
64 break;
65 }
66 }
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 13/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
66 }
We’ve
67 made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
68 you to review them.
log("Web RTCByPeer
continuing to useCreated.");
Connection our services, you agree to the new Terms of Service and
acknowledge
69 the Privacy Policy applies to you.
document.getElementById("sendOfferButton").disabled = false;

Continue
Here the video and audio streams are added to the RTCPeerConnection so that it can be
streamed when a peer to peer connection is successfully established.

ontrack handler will be fired whenever a video or audio stream is received from
RTCPeerConnection and will set these to a video element for playback.

ondatachannel handler will be fired whenever the created data channel is received
from the other peer (Caller). This channel will be used to send text messages
between the two peers.

onicecandidate handler will be fired whenever an ICE Candidate is received from


Stun/Turn server. This candidate will be sent to the other peer as soon as it is
received.

Please note that above order of execution for creating web socket and WebRTC peer
connection will be the same for both peers (Caller and Receiver).

Code Execution Flow for Establishing a Peer to Peer Connection


1. Both Caller and Receiver will open the file WebRTCChat.html in their browser. This
will execute connectToWebSocket and createRTCPeerConnection in both peers.

2. One user (Caller) will click “Call” button and this will execute the following function.

1 function createAndSendOffer(){
2 if(channel){
3 channel.close();
4 }
5
6 // Create Data channel
7 channel = connection.createDataChannel('channel', {});
8 setChannelEvents(channel);
9
10 // Create Offer
11 connection.createOffer().then(
12 offer => {
13 log('Sent The Offer ');
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 14/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
13 log( Sent The Offer. );
We’ve
14 made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
15 you to review them. By continuing
// Send Offer toto use our
other services, you agree to the new Terms of Service and
peer
acknowledge
16
the Privacy Policy applies to you.
socket.send(JSON.stringify(
17 { Continue
18 action: 'onMessage',
19 type: 'offer',
20 data: offer,
21 id: clientId
22 }
23 ));
24
25 // Set Offer for negotiation
26 connection.setLocalDescription(offer);
27 },
28 error => {
29 log('Error when creating an offer.');
30 console.error(error);
31 }
32 );
33 }

An Offer will be created and saved in Caller’s session with setLocalDescription

function. Afterwards, the Offer will be sent to the other user (Receiver) over the web
socket.

3. As soon as the Offer is created, onicecandidate event handler will be fired and the
generated ICE Candidates will be sent to the Receiver via the web socket.

4. On the Receiver’s end, handleOffer function will be executed and the Offer sent from
the Caller will be saved in Receiver’s session with setRemoteDescription function.

5. On the Receiver’s end, handleCandidate function will be executed and ICE Candidates
received from the Caller will be added to the Receiver’s RTCPeerConnection.

6. Receiver will click “Answer” button and this will execute the following function.

1 function createAndSendAnswer(){
2
3 // Create Answer
4 connection.createAnswer().then(
5 {
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 15/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
5 answer => {
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
6 log('Sent The Answer.');
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
7
acknowledge the Privacy Policy applies to you.
8 // Set Answer for negotiation
9 Continue
connection.setLocalDescription(answer);
10
11 // Send Answer to other peer
12 socket.send(JSON.stringify(
13 {
14 action: 'onMessage',
15 type: 'answer',
16 data: answer,
17 id: clientId
18 }
19 ));
20 },
21 error => {
22 log('Error when creating an answer.');
23 console.error(error);
24 }
25 );
26 }

j ❤ i view raw
An Answer will be created and saved in Receiver’s session with setLocalDescription.

Afterwards, the created Answer will be sent to the other user (Caller) over the web
socket.

7. On the Caller’s end, handleAnswer event handler will be fired and the Answer sent
from the Receiver will be saved in Caller’s session with setRemoteDescription function.

Now a peer to peer connection should be established between the two peers.

Please have a look at the full source code for the WebRTCChat.html file below.

1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <meta http-equiv="X-UA-Compatible" content="ie=edge">
7 <title>WebRTC Video Chat</title>
8 <style>
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 16/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
8 <style>
We’ve9made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
10 you to review them. By continuing
#videoContainer { to use our services, you agree to the new Terms of Service and
acknowledge
11 the Privacydisplay:
Policy applies
table;to you.
12 margin: 0 auto;
Continue
13 }
14
15 video{
16 margin: 10px;
17 border: 2px solid #000000;
18 }
19
20 textarea {
21 width: 100%;
22 height: 150px;
23 resize: none;
24 box-sizing : border-box;
25 }
26
27 .center {
28 margin: auto;
29 width: 70%;
30 border: 3px solid green;
31 padding: 20px;
32 }
33
34 input, button{
35 width: 100%;
36 box-sizing : border-box;
37 }
38
39 video{
40 width: 40%;
41 height: 100%;
42 }
43
44 button {
45 border: 1px solid #000000;
46 background-color: #0099ff;
47 color: #ffffff;
48 padding: 5px 10px;
49 }
50
51 button:disabled,
52 button[disabled]{

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 17/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
53 border: 1px solid #999999;
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
54 background-color: #cccccc;
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
55
acknowledge the Privacycolor: #666666;
Policy applies to you.
56 }
57 Continue
58 th, td {
59 text-align: center;
60 }
61 </style>
62 </head>
63 <body>
64
65 </body>
66
67 <div class="center">
68 <button id="sendOfferButton" onclick="createAndSendOffer()">Call</button>
69 <button id="answerButton" onclick="createAndSendAnswer()">Answer</button>
70 <button id="hangUpButton" onclick="disconnectRTCPeerConnection()">Hang Up</button><
71
72 <input id="messageInput" type="text" size="80" placeholder="Enter message to send">
73 <button id="sendMessageButton" onclick="sendMessage()">Send Message</button><br/><b
74
75 <p style="text-align: center">Tap to Change Front/Back Camera</p>
76
77 <div id="videoContainer">
78 <video id="localVideo" onclick="switchMobileCamera()" muted autoplay playsinlin
79 <video id="remoteVideo" autoplay playsinline></video>
80 </div>
81
82 <table style="width:100%">
83 <tr>
84 <th>Outbound Video Stats</th>
85 <th>Inbound Video Stats</th>
86 </tr>
87 <tr>
88 <td><div readonly id="outBoundstats"></div></td>
89 <td><div readonly id="inBoundstats"></div></td>
90 </tr>
91 </table>
92
93 </div>
94 <br/><br/>
95
96 <textarea readonly id="chatTextArea"></textarea><br/><br/>
97
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 18/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve98made changes to ourreadonly


<textarea Terms ofid="logs"></textarea><br/><br/>
Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
99 you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge
100 the Privacy Policy applies to you.
</div>
101
Continue
102
103 <script>
104 const webSocketConnection = "WEBSOCKET_URL";
105 const turnServerIPAddress = "TURN_SERVER_IP_ADDRESS";
106 const turnServerPort = "TURN_SERVER_PORT";
107 const turnServerUserName = "TURN_SERVER_USERNAME";
108 const turnServerPassword = "TURN_SERVER_PASSWORD";
109
110 var cameraMode = "user";
111 var inBoundTimestampPrev = 0;
112 var inBoundBytesPrev = 0;
113 var outBoundTimestampPrev = 0;
114 var outBoundBytesPrev = 0;
115
116 existingTracks = [];
117
118 var socket, localStream, connection, clientId = uuidv4(), channel;
119
120 const configuration = {
121 iceServers: [
122 {
123 urls: 'stun:' + turnServerIPAddress + ':' + turnServerPort
124 },
125 {
126 urls: 'turn:' + turnServerIPAddress + ':' + turnServerPort,
127 username: turnServerUserName,
128 credential: turnServerPassword
129 }
130 ]
131 }
132
133 disableAllButtons();
134
135 getLocalWebCamFeed();
136
137
138 /*
139 This function creates the socket connection and WebRTC connection.
140 This is also responsible for changing media tracks when user switches mobile ca
141 */
142 f ti i iti tS k tA dP C ti ( t ){
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 19/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
142 function initiatSocketAndPeerConnection(stream){
We’ve
143
made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
document.getElementById("localVideo").srcObject = stream;
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
144
acknowledge the Privacy Policy applies to you.
145 if(typeof socket === 'undefined'){
146 connectToWebSocket(); Continue
147 }else{
148 existingTracks.forEach(function (existingTrack, index) {
149 existingTrack.replaceTrack(localStream.getTracks()[index]);
150 });
151 }
152 }
153
154 function disableAllButtons(){
155 document.getElementById("sendOfferButton").disabled = true;
156 document.getElementById("answerButton").disabled = true;
157 document.getElementById("sendMessageButton").disabled = true;
158 document.getElementById("hangUpButton").disabled = true;
159 }
160
161 /*
162 Send messages via Data Channel
163 */
164 function sendMessage(){
165 var messageText = document.getElementById("messageInput").value;
166
167 channel.send(JSON.stringify({
168 "message": messageText
169 }));
170
171 document.getElementById("chatTextArea").value += messageText + '\n';
172 }
173
174 function disconnectRTCPeerConnection(){
175 connection.close();
176 }
177
178 /*
179 Connect to the web socket and handle recieved messages from web sockets
180 */
181 function connectToWebSocket(){
182 socket = new WebSocket(webSocketConnection);
183
184 // Create WebRTC connection only if the socket connection is successful.
185 socket.onopen = function(event) {
186 log('WebSocket Connection Open.');
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 20/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

187made changes to our


We’ve createRTCPeerConnection();
Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
188
encourage };
you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge
189 the Privacy Policy applies to you.
190 // Handle messages recieved in socket
Continue
191 socket.onmessage = function(event) {
192 jsonData = JSON.parse(event.data);
193
194 switch (jsonData.type){
195 case 'candidate':
196 handleCandidate(jsonData.data, jsonData.id);
197 break;
198 case 'offer':
199 handleOffer(jsonData.data, jsonData.id);
200 break;
201 case 'answer':
202 handleAnswer(jsonData.data, jsonData.id);
203 break;
204 default:
205 break
206 }
207 };
208
209 socket.onerror = function(event) {
210 console.error(event);
211 log('WebSocket Connection Error. Make sure web socket URL is correct and we
212 };
213
214 socket.onclose = function(event) {
215 log('WebSocket Connection Closed. Please Reload the page.');
216 document.getElementById("sendOfferButton").disabled = true;
217 document.getElementById("answerButton").disabled = true;
218 };
219 }
220
221 function log(message){
222 document.getElementById("logs").value += message + '\n';
223 }
224
225 /*
226 Get local camera permission from user and initiate socket and WebRTC connection
227 */
228 function getLocalWebCamFeed(){
229
230 // width: { ideal: 4096 },
231 // height: { ideal: 2160 }
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 21/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
231 // height: { ideal: 2160 }
We’ve
232made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
233 you to review them. By= continuing
constraints { to use our services, you agree to the new Terms of Service and
acknowledge
234
the Privacyaudio:
Policy applies
true,
to you.
235 video: { Continue
236 facingMode: cameraMode,
237 width: { ideal: 4096 },
238 height: { ideal: 2160 }
239 }
240 }
241
242 navigator.getWebcam = (navigator.getUserMedia || navigator.webKitGetUserMedia |
243 if (navigator.mediaDevices.getUserMedia) {
244 navigator.mediaDevices.getUserMedia(constraints)
245 .then(function (stream) {
246 localStream = stream;
247 initiatSocketAndPeerConnection(stream);
248 })
249 .catch(function (e) { log(e.name + ": " + e.message); });
250 }
251 else {
252 navigator.getWebcam({ audio: true, video: true },
253 function (stream) {
254 localStream = stream;
255 initiatSocketAndPeerConnection(stream);
256 },
257 function () { log("Web cam is not accessible.");
258 });
259 }
260 }
261
262 /*
263 This is responsible for creating an RTCPeerConnection and handle it's events.
264 */
265 function createRTCPeerConnection(){
266 pushStats();
267 connection = new RTCPeerConnection(configuration);
268
269 // Add both video and audio tracks to the connection
270 for (const track of localStream.getTracks()) {
271 log("Sending Stream.")
272 existingTracks.push(connection.addTrack(track, localStream));
273 }
274
275 // This event handles displaying remote video and audio feed from the other pee

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 22/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
276 connection.ontrack = event => {
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
277 log("Recieved Stream.");
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
278
acknowledge the Privacydocument.getElementById("remoteVideo").srcObject
Policy applies to you. = event.streams[0];
279 }
280 Continue
281 // This event handles the received data channel from the other peer
282 connection.ondatachannel = function (event) {
283 log("Recieved a DataChannel.")
284 channel = event.channel;
285 setChannelEvents(channel);
286 document.getElementById("sendMessageButton").disabled = false;
287 };
288
289 // This event sends the ice candidates generated from Stun or Turn server to th
290 connection.onicecandidate = event => {
291 if (event.candidate) {
292 log("Sending Ice Candidate - " + event.candidate.candidate);
293
294 socket.send(JSON.stringify(
295 {
296 action: 'onMessage',
297 type: 'candidate',
298 data: event.candidate,
299 id: clientId
300 }
301 ));
302 }
303 }
304
305 // This event logs messages and handles button state according to WebRTC connec
306 connection.onconnectionstatechange = function(event) {
307 switch(connection.connectionState) {
308 case "connected":
309 log("Web RTC Peer Connection Connected.");
310 document.getElementById("answerButton").disabled = true;
311 document.getElementById("sendOfferButton").disabled = true;
312 document.getElementById("hangUpButton").disabled = false;
313 document.getElementById("sendMessageButton").disabled = false;
314 break;
315 case "disconnected":
316 log("Web RTC Peer Connection Disconnected. Please reload the page t
317 disableAllButtons();
318 break;
319 case "failed":
320 log("Web RTC Peer Connection Failed. Please reload the page to reco
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 23/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
g( p g
We’ve
321made changes to our Termsconsole.log(event);
of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
322 you to review them. By continuing to use our services, you agree to the new Terms of Service and
disableAllButtons();
acknowledge
323 the Privacy Policy applies
break;to you.
324 case "closed":
Continue
325 log("Web RTC Peer Connection Failed. Please reload the page to reco
326 disableAllButtons();
327 break;
328 default:
329 break;
330 }
331 }
332
333 log("Web RTC Peer Connection Created.");
334 document.getElementById("sendOfferButton").disabled = false;
335 }
336
337 /*
338 Creates and sends the Offer to the Receiver
339 Creates a Data channel for exchanging text messages
340 This function is invoked by the Caller
341 */
342 function createAndSendOffer(){
343 if(channel){
344 channel.close();
345 }
346
347 // Create Data channel
348 channel = connection.createDataChannel('channel', {});
349 setChannelEvents(channel);
350
351 // Create Offer
352 connection.createOffer().then(
353 offer => {
354 log('Sent The Offer.');
355
356 // Send Offer to other peer
357 socket.send(JSON.stringify(
358 {
359 action: 'onMessage',
360 type: 'offer',
361 data: offer,
362 id: clientId
363 }
364 ));
365
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 24/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
365
We’ve
366
made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
// Set Offer for negotiation
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
367 connection.setLocalDescription(offer);
acknowledge the Privacy Policy applies to you.
368 },
369 error => { Continue
370 log('Error when creating an offer.');
371 console.error(error);
372 }
373 );
374 }
375
376 /*
377 Creates and sends the Answer to the Caller
378 This function is invoked by the Receiver
379 */
380 function createAndSendAnswer(){
381
382 // Create Answer
383 connection.createAnswer().then(
384 answer => {
385 log('Sent The Answer.');
386
387 // Set Answer for negotiation
388 connection.setLocalDescription(answer);
389
390 // Send Answer to other peer
391 socket.send(JSON.stringify(
392 {
393 action: 'onMessage',
394 type: 'answer',
395 data: answer,
396 id: clientId
397 }
398 ));
399 },
400 error => {
401 log('Error when creating an answer.');
402 console.error(error);
403 }
404 );
405 }
406
407 /*
408 Accepts ICE candidates received from the Caller
409 */
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 25/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

410made changes
We’ve function handleCandidate(candidate,
to our Terms of Service and Privacyid){
Policy. They take e ect on September 1, 2020, and we
encourage
411 you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge
412 the Privacy Policy
// Avoid applies tothe
accepting you.ice candidate if this is a message created by the curren
413 if(clientId != id){
Continue
414 log("Adding Ice Candidate - " + candidate.candidate);
415 connection.addIceCandidate(new RTCIceCandidate(candidate));
416 }
417 }
418
419 /*
420 Accepts Offer received from the Caller
421 */
422 function handleOffer(offer, id){
423
424 // Avoid accepting the Offer if this is a message created by the current peer
425 if(clientId != id){
426 log("Recieved The Offer.");
427 connection.setRemoteDescription(new RTCSessionDescription(offer));
428 document.getElementById("answerButton").disabled = false;
429 document.getElementById("sendOfferButton").disabled = true;
430 }
431 }
432
433 /*
434 Accetps Answer received from the Receiver
435 */
436 function handleAnswer(answer, id){
437
438 // Avoid accepting the Answer if this is a message created by the current peer
439 if(clientId != id){
440 log("Recieved The Answer");
441 connection.setRemoteDescription(new RTCSessionDescription(answer));
442 }
443 }
444
445 /*
446 Generate a unique ID for the peer
447 */
448 function uuidv4() {
449 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
450 var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
451 return v.toString(16);
452 });
453 }
454
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 26/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
454
We’ve
455made changes
/* to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage
456 you to review
Handlethem.
DataByChannel
continuing to use our services, you agree to the new Terms of Service and
events
acknowledge
457
the
*/
Privacy Policy applies to you.
458 function setChannelEvents(channel) {
Continue
459 channel.onmessage = function (event) {
460 var data = JSON.parse(event.data);
461 document.getElementById("chatTextArea").value += data.message + '\n';
462 };
463
464 channel.onerror = function (event) {
465 log('DataChannel Error.');
466 console.error(event)
467 };
468
469 channel.onclose = function (event) {
470 log('DataChannel Closed.');
471 disableAllButtons();
472 };
473 }
474
475 /*
476 Switch between front and back camera when opened in a mobile browser
477 */
478 function switchMobileCamera(){
479 if (cameraMode == "user") {
480 cameraMode = "environment";
481 } else {
482 cameraMode = "user";
483 }
484
485 getLocalWebCamFeed();
486 }
487
488 function pushStats(){
489 let inBoundStatsDiv = document.getElementById("inBoundstats");
490 let outBoundstatsDiv = document.getElementById("outBoundstats");
491
492 window.setInterval(function() {
493 connection.getStats(null).then(stats => {
494 let inBoundBitrate;
495 let outBoundBitrate;
496
497 stats.forEach(report => {
498 if (report.type === 'inbound-rtp' && report.mediaType === 'video'){
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 27/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
499 let now = report.timestamp;
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
500 let bytes = report.bytesReceived;
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
501 if (inBoundTimestampPrev)
acknowledge the Privacy Policy applies to you. {
502 inBoundBitrate = 0.125 * (8 * (bytes - inBoundBytesPrev) /
503 Continue= Math.floor(inBoundBitrate);
inBoundBitrate
504 }
505 inBoundBytesPrev = bytes;
506 inBoundTimestampPrev = now;
507 }
508 else if(report.type === 'outbound-rtp' && report.mediaType === 'vid
509 let now = report.timestamp;
510 let bytes = report.bytesSent;
511 if (outBoundTimestampPrev) {
512 outBoundBitrate = 0.125 * (8 * (bytes - outBoundBytesPrev)
513 outBoundBitrate = Math.floor(outBoundBitrate);
514 }
515 outBoundBytesPrev = bytes;
516 outBoundTimestampPrev = now;
517 }
518
519 if(isNaN(inBoundBitrate)){
520 inBoundBitrate = 0;
521 }
522

Configuring and Hosting The Client Application in S3


Open the WebRTCChat.html and replace following values and save changes.

WEBSOCKET_URL - Replace this with the web socket URL copied in “step 1”.

TURN_SERVER_IP_ADDRESS - Replace this with the EC2 public IP address copied in “step 2”.

TURN_SERVER_PORT - Replace this with port value provided when starting Coturn in “step

3.d” (Port value 3478).

TURN_SERVER_USERNAME - Replace this with the username you provided when starting

Coturn in “step 3.d”

TURN_SERVER_PASSWORD - Replace this with the password you provided when starting

Coturn in “step 3.d”

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 28/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

In order
We’ve made to maketothe
changes ourapplication accessible
Terms of Service from
and Privacy theThey
Policy. internet, it needs
take e ect to be hosted
on September 1, 2020,in
and we
encourage you to
AWS S3 bucket. review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Deploying to AWS S3 Bucket Continue

1. Go to AWS Console and create an S3 bucket.

2. Make the bucket public as displayed below.

3. Upload the WebRTCChat.html file to the created S3 bucket and make it public as
well.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 29/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Continue

Testing
1. Now open the WebRTCChat.html file using the public URL (Displayed above) in
both Caller and Receiver’s browsers.

2. Caller clicks on “Call” button.

3. Receiver clicks on “Answer” button.

4. You should be able to have a video call with each other as displayed below and the
text chat should be working as well.

Here you can see me making a video call (From Sri Lanka) with my friend in Japan via
iOS Safari and it works perfectly.

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 30/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium

We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.

Compatibility Continue

As of now this application is tested in Windows Chrome Version 77.0.3865.90 (Official


Build) (64-bit) and iOS 13.1.2 Safari browser.

In iOS WebRTC is not supported in any other browsers except Safari.

Go to this link to see supported platforms.

Summary
WebRTC support is available not only in browsers but on other platforms natively as well
(Via Libraries). But the concepts is the same and now you know how you can leverage it
to stream data (Files, Texts, Images, Video and Audio) real time in any of your
application as needed.

Cheers!

References

ICE and WebRTC: What Is This Sorcery? We Explain... " Temasys.io


Posted On August 19, 2016 by Sherwin Sim in Blog, Tutorials We support many
types of customers at Temasys. They all…

temasys.io

What is a STUN/TURN Server? · Blog


Technology De nition
blog.ivrpowers.com

WebRTC Home | WebRTC


WebRTC is a free, open project that provides browsers and mobile applications with Real-Time
Communications (RTC)…
webrtc org
https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 31/32
8/25/2020 WebRTC Video Chat App Development | by Suminda Niroshan | The Startup | Medium
webrtc.org
We’ve made changes to our Terms of Service and Privacy Policy. They take e ect on September 1, 2020, and we
encourage you to review them. By continuing to use our services, you agree to the new Terms of Service and
acknowledge the Privacy Policy applies to you.
coturn/coturn Continue
This project evolved from rfc5766-turn-server project
(https://code.google.com/p/rfc5766-turn-server/). There are many…

github.com

SumindaD/WebRTC_AWS_Websocket
This repo contains Serverless Framework project for a simple AWS Websocket chat app Install required
npm packages rst…

github.com

WebRTC Aws Websockets Peer To Peer Real Time Streaming Serverless Framework

About Help Legal

Get the Medium app

https://medium.com/swlh/webrtc-video-chat-application-2e1789cc9e37 32/32

You might also like