Communication is an important way to build up a relationship, which is one of the key points of doing business. Therefore it is a good idea to provide a means of video communication with your clients, in addition to text and audio, because your body language, facial expression and the tone of your voice help to convey your sincere interest in your clients’ needs and thoughts.

Want to create a peer to peer video chats on your web pages without installing plugins or any other third-party software? WebRTC application development is a relevant answer for you. Tune in, and this tutorial will show you how to create a video chat using EasyRTC and Webix UI Library, created by our software development company and available under GPL.

This is going to be a simple WebRTC example that can be used for video calls between two users. Before your immersion, don’t forget to take your friends with you:

any WebRTC-aware browser (Google, Opera, Firefox, MS Edge, or Safari 11)

Node.js

Step 1 – Why WebRTC?

WebRTC is a free, open project that can help you organize:

Video conferences with your clients and colleagues

Video tech support, as it’s easier to explain a problem and to show the solution to it, when you see other people’s screens and the people themselves

Online tutorials and courses, because users can see a tutor’s face, and this is especially important for building up trust. Besides, it’s useful if you teach some practical skills like languages

WebRTC apps work across multiple browsers and platforms. You need to use any browser that supports WebRTC: Google, Opera, Firefox, MS Edge, or Safari.

You can forget that Big Brother is watching you, as all data sent between browsers is encrypted using DTLS and SRTP. Mind that you can access the demo only via https, not http. You can forget about distorted or pixelated faces, as VP8 codec ensures excellent quality of a video stream.

EasyRTC is a free open source framework with its powerful server/client-side API helps build WebRTC apps out of the box. We’ll use this framework to create our WebRTC peer to peer example.

In the following four steps, you will learn how to start a server, create a basic UI for a video chat example, add video streams, and some necessary features. In the end, you’ll have a full-fledged app using a free WebRTC server.

Step 2 – Starting WebRTC Server

Installing Dependencies

First of all, you need to install EasyRTC framework and other necessary modules for Node.js. In the console, go to your project folder and run this command:

npm install easyrtc express serve-static socket.io 1 npm install easyrtc express serve - static socket . io

Done, guys. Now it’s time to write the code.

Writing server.js

In your project folder, create a file named server.js, that will contain code for setting server options, which is a standard procedure:

import of all the necessary modules

setup and configuration of an Express http server; a subfolder named static will be the web root, where you will place your HTML, CSS files, avatars and the file with the app logic

server; a subfolder named will be the web root, where you will place your files, avatars and the file with the app logic launching the Express http server on port 8080 (by default) and Socket.io, so that the latter could attach itself to the Express server

server on port 8080 (by default) and so that the latter could attach itself to the server overriding the default easyrtcAuth listener, so that its callback could be directly accessed to handle errors and save credentials (the easyrtcAuth event is fired when an incoming easyrtcAuth message is received from a client)

listener, so that its callback could be directly accessed to handle errors and save credentials (the event is fired when an incoming message is received from a client) launching an EasyRTC server

launch listening on localhost:8080

You can find the code for server.js on GitHub.

Starting a Server

Now that the file is ready, you can start your server. In the console, run a command:

node server.js 1 node server . js

If all goes well, the server will be initiated, and you’ll see something like this:

So far, so good! It’s time to create the UI for the chat.

Step 3 – Creating a Basic UI

Adding Static Files

Next, you are to create a subfolder named static and add the following files to it:

– index.html, the purpose of which is to include Webix lib files:

<script src="//cdn.webix.com/edge/webix.js" type="text/javascript"></script> 1 <script src = "//cdn.webix.com/edge/webix.js" type = "text/javascript" > </script>

…EasyRTC:

<script src="/socket.io/socket.io.js" type="text/javascript"></script> <script src="/easyrtc/easyrtc.js" type="text/javascript"> </script> 1 2 <script src = "/socket.io/socket.io.js" type = "text/javascript" > </script> <script src = "/easyrtc/easyrtc.js" type = "text/javascript" > </script>

and the files for the project itself (app.css and webrtc.js).

– the app.css file that contains style for the UI.

Now create a subfolder for images and place an image that you want to use as an avatar (for example, you can name it avatar.jpg; its size should be 300×300 px).

Writing Webix UI

In the project folder, create webrtc.js. This is the main file of our WebRTC video example, as it will contain all the logic. Let’s dive into it.

First, create a list view, that will display all the people in the chat:

var contactsList = { header : "Rooms", view : "list", template : ``, //...config }; 1 2 3 4 5 6 var contactsList = { header : "Rooms" , view : "list" , template : ` ` , //...config } ;

and a container for video streams:

var chat = { css:"absarea", template:`Video stream will be here` }; 1 2 3 4 var chat = { css : "absarea" , template : ` Video stream will be here ` } ;

Next, create a window with a log in form, that will appear when users access the chat or reload the page. The form will contain the Start ! button: on click, the name will be verified and added to the list.

var win = webix.ui ({ view: "window", position:"top", head:false, modal:true, body: { view:"form", rows:[ { view:"text", name:"name", label:"Your Name" /* , value:funnyName() */}, { view:"button", value:"Start !", click:function(){ var name = this.getFormView().getValues().name; if (!easyrtc.isNameValid(name)) webix.message({ type:"error", text:"Invalid name" }); else { //...add the user to the contact list } }} ] } }); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var win = webix . ui ( { view : "window" , position : "top" , head : false , modal : true , body : { view : "form" , rows : [ { view : "text" , name : "name" , label : "Your Name" /* , value:funnyName() */ } , { view : "button" , value : "Start !" , click : function ( ) { var name = this . getFormView ( ) . getValues ( ) . name ; if ( ! easyrtc . isNameValid ( name ) ) webix . message ( { type : "error" , text : "Invalid name" } ) ; else { //...add the user to the contact list } } } ] } } ) ;

You can add the funnyName() function, that is going to generate a random combo of two words from a predefined set for a name and display it in the text input:

function funnyName(){ var first = ["Agile", "Strong", "Tricky", "Shiny", "Gloom"]; var second = ["Tree", "Cat", "Boss", "User", "Rabbit"]; return first[Math.floor(Math.random()*first.length)] + " " + second[Math.floor(Math.random()*second.length)]; } //...the window with the form { view:"text", name:"name", label:"You Name", value:funnyName() } 1 2 3 4 5 6 7 8 function funnyName ( ) { var first = [ "Agile" , "Strong" , "Tricky" , "Shiny" , "Gloom" ] ; var second = [ "Tree" , "Cat" , "Boss" , "User" , "Rabbit" ] ; return first [ Math . floor ( Math . random ( ) * first . length ) ] + " " + second [ Math . floor ( Math . random ( ) * second . length ) ] ; } //...the window with the form { view : "text" , name : "name" , label : "You Name" , value : funnyName ( ) }

Next, create a toolbar and initialize the UI:

webix.ui({ rows: [ { view:"toolbar", cols:[ { view:"label", label : "Webix WebRTC Chat" }, {}, ]}, { cols:[ contactsList, chat ]} ] }); 1 2 3 4 5 6 7 8 9 10 11 12 webix . ui ( { rows : [ { view : "toolbar" , cols : [ { view : "label" , label : "Webix WebRTC Chat" } , { } , ] } , { cols : [ contactsList , chat ] } ] } ) ;

We’ve created the UI! You can view the complete source code.

Now, if you try accessing localhost:8080, you will see something like this:

Awesome. Let’s move on to the next step.

Step 4 – Adding Video Streams

In this step, you are to modify your webrtc.js. Let’s begin from the user list.

Adding Real User List

Move the configuration of the list to var config (Later in this step you will need to add the configuration to the event for adding or deleting users):

var config = { server:"/", users:function(room, people, me){ var list = $$("contactsList"); //updating user list } } }; 1 2 3 4 5 6 7 8 var config = { server : "/" , users : function ( room , people , me ) { var list = $ $ ( "contactsList" ) ; //updating user list } } } ;

Next, add an event handler to the list, so that when a user selects an item, the function for video calls would be invoked (we’ll define the function later in this step):

on:{ onBeforeSelect: (id) => doCall(id) } 1 on : { onBeforeSelect : ( id ) = > doCall ( id ) }

Enable Mirror Stream

Now you need to add 2 video areas to the chat container:

a mirror that will display the face of the caller

a “window to Universe,” which is the main window

var chat = { css:"absarea", template:` 1 2 3 var chat = { css : "absarea" , template : `

`

};

Enable Video Calls

First, you need to create a connection with the WebRTC server. For that, define the doConnect() function, that will take the configuration of the contact list as a parameter and make use of the EasyRTC API. In case of an error, users will see an error message.

function doConnect(config) { easyrtc.setVideoDims(640,480); easyrtc.setUsername(config.name); easyrtc.setRoomOccupantListener(config.users); easyrtc.setSocketUrl(config.server); easyrtc.easyApp("WebixWebRTC", "mirrorVideo", ["windowToUniverse"], function(id){ config.$userId = id }, function(){ var text = "Connection failed"; if(code === "MEDIA_ERR") text += ". Cannot find a local web camera"; if(code === "MEDIA_WARNING") text += ". Video width and height are inappropriate"; if(code === "SYSTEM_ERR") text += ". Check your network settings"; if(code === "ALREADY_CONNECTED") text += ". You are already connected"; webix.message({ type:"error", text:text }); }); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function doConnect ( config ) { easyrtc . setVideoDims ( 640 , 480 ) ; easyrtc . setUsername ( config . name ) ; easyrtc . setRoomOccupantListener ( config . users ) ; easyrtc . setSocketUrl ( config . server ) ; easyrtc . easyApp ( "WebixWebRTC" , "mirrorVideo" , [ "windowToUniverse" ] , function ( id ) { config . $ userId = id } , function ( ) { var text = "Connection failed" ; if ( code === "MEDIA_ERR" ) text += ". Cannot find a local web camera" ; if ( code === "MEDIA_WARNING" ) text += ". Video width and height are inappropriate" ; if ( code === "SYSTEM_ERR" ) text += ". Check your network settings" ; if ( code === "ALREADY_CONNECTED" ) text += ". You are already connected" ; webix . message ( { type : "error" , text : text } ) ; } ) ; }

The doConnect() function will be invoked when a user clicks Start ! on the login form, and the name is verified.

At this point, we can connect, and what we have to do now is enable video calls. Let’s define the doCall() function, which is the same function that will be invoked on the selection of a list item. If a caller clicks on their name, the function does nothing:

function doCall(easyrtcid) { if (easyrtcid < 0) return false; //… } 1 2 3 4 function doCall ( easyrtcid ) { if ( easyrtcid < 0 ) return false ; //… }

If you want to talk face-to-face to yourself, a real old-school glass mirror will suffice :)

Next, if something goes wrong, an error message will be shown:

//...previous code easyrtc.call( easyrtcid, function(caller) { }, function(errorMessage) { webix.message({ type:"error", text:errorMessage }); }, //… 1 2 3 4 5 6 7 8 9 10 //...previous code easyrtc . call ( easyrtcid , function ( caller ) { } , function ( errorMessage ) { webix . message ( { type : "error" , text : errorMessage } ) ; } , //…

In case the recipient doesn’t want to talk to the caller in the first place, the latter will be notified of that as well:

//...prev code function(accepted, caller) { if (!accepted){ webix.message(easyrtc.idToName(caller)+" has rejected your call"); } } ); } 1 2 3 4 5 6 7 8 //...prev code function ( accepted , caller ) { if ( ! accepted ) { webix . message ( easyrtc . idToName ( caller ) + " has rejected your call" ) ; } } ) ; }

You can also view the source code.

Great! The basic video chat example is created, though we need to add some necessary features like a button to end a call, and a label to display the status. Besides, we’ll make the app more verbose by adding the text for call requests and one more error message.

Step 5 – Polishing UX

Adding Call Request

Let’s add call requests:

– if someone calls, the app will ask users if they want to accept it (the user might be involved in other conversation at that moment):

if( easyrtc.getConnectionCount() > 0 ) webix.confirm({ text:"Drop the current call and accept the new one from " + name + " ?", callback }); else webix.confirm({ text: "Accept an incoming call from " + name + " ?", callback }); 1 2 3 4 if ( easyrtc . getConnectionCount ( ) > 0 ) webix . confirm ( { text : "Drop the current call and accept the new one from " + name + " ?" , callback } ) ; else webix . confirm ( { text : "Accept an incoming call from " + name + " ?" , callback } ) ;

– if the user accepts, the app will hang up on the previous person, if needed, and accept the new call:

easyrtc.setAcceptChecker( function(caller, cb) { var name = easyrtc.idToName(caller); var callback = function(wasAccepted) { if (wasAccepted){ if (easyrtc.getConnectionCount() > 0 ) easyrtc.hangupAll(); //... } cb(wasAccepted); }; //... }); 1 2 3 4 5 6 7 8 9 10 11 12 easyrtc . setAcceptChecker ( function ( caller , cb ) { var name = easyrtc . idToName ( caller ) ; var callback = function ( wasAccepted ) { if ( wasAccepted ) { if ( easyrtc . getConnectionCount ( ) > 0 ) easyrtc . hangupAll ( ) ; //... } cb ( wasAccepted ) ; } ; //... } ) ;

Adding Status and Hangup Button

To add the status label and a button to end calls, let’s modify the toolbar first:

{ view:"label", id:"status", css:"status", value:"", width: 200 }, { view:"button", id:"endcall", value:"End Call", width: 100, click:function(){ $$("endcall").hide(); easyrtc.hangupAll(); $$("contactsList").unselectAll() $$("status").setValue(""); }, hidden:true } 1 2 3 4 5 6 7 8 { view : "label" , id : "status" , css : "status" , value : "" , width : 200 } , { view : "button" , id : "endcall" , value : "End Call" , width : 100 , click : function ( ) { $ $ ( "endcall" ) . hide ( ) ; easyrtc . hangupAll ( ) ; $ $ ( "contactsList" ) . unselectAll ( ) $ $ ( "status" ) . setValue ( "" ) ; } , hidden : true }

Okay, now let’s teach our app to notify users of disconnection (e.g., in case the recipient closes the chat). Modify the doConnect() function by adding these lines of code:

easyrtc.setPeerClosedListener(function(){ if ($$("endcall").isVisible()){ webix.message("You were disconnected"); } }); 1 2 3 4 5 easyrtc . setPeerClosedListener ( function ( ) { if ( $ $ ( "endcall" ) . isVisible ( ) ) { webix . message ( "You were disconnected" ) ; } } ) ;

Add 2 more lines of code to truncate the status and hide the button, when the user is disconnected:

$$("endcall").hide(); $$("status").setValue(""); 1 2 $ $ ( "endcall" ) . hide ( ) ; $ $ ( "status" ) . setValue ( "" ) ;

Besides, add 2 lines of code to easyrtc.setAcceptChecker() to show the button and update the status, if the call has been accepted:

$$("endcall").show(); $$("status").setValue(name); 1 2 $ $ ( "endcall" ) . show ( ) ; $ $ ( "status" ) . setValue ( name ) ;

Now we are on to the doCall() function. If the call is made successfully, the button will be shown, and the status will be updated correspondingly:

function(caller) { $$("endcall").show(); $$("status").setValue(easyrtc.idToName(caller)); }, 1 2 3 4 function ( caller ) { $ $ ( "endcall" ) . show ( ) ; $ $ ( "status" ) . setValue ( easyrtc . idToName ( caller ) ) ; } ,

Besides, you need to add code for setting the status before attempting a connection and for truncating the status if the call has been rejected.

You can check out the source code of the demo.

This is it, guys. We’ve done it. See a live demo.

Conclusion

WebRTC development is good if you plan to create a peer to peer connection and video chats in particular. You’ve seen how EasyRTC framework makes it easier to use the WebRTC API and how to create a basic UI with Webix. And this is not all you can do. You can further modify the UI and add more features to make your chat even better.

Related links: