WebRTC Making an application with blackjack and video calls

Dear reader, before we start writing the code, let's take a look at the concept of video calls.

Imagine the situation: we have a chat platform and we need to fasten video calls to it, that is, a certain Vasya is sitting online and he wants to call Petya, to implement such a feature, we need WebSocket technology .

Well, let's raise our WebSocket server, node.js will help us with this;
Create the sockets.js file and write the server socket code there:

const WebSocketServer = require('websocket').server;
const http = require('http');

const server = http.createServer(function(request, response) {
 //    ,    ,  http
});
server.listen(1337, function() {});

//   
const wsServer = new WebSocketServer({
  httpServer: server
});

wsServer.on('request', function(request) {
  let connection = request.accept(null, request.origin);
//   
})

Create an index.html file and write the code there to open a socket connection:

     <video autoplay muted height='300' width='300' style="position:fixed;bottom:0;left:0;z-index: 9999;" src="" id='my'>
          </video> <!--   --> 

          <video autoplay height='300' width='300' style="position:fixed;bottom:0;left:300px;z-index: 999999;" src="" id='not_my'>
          </video> <!--  -->

Now create and connect the script.js file to our html file:

  let connection = new WebSocket('ws://127.0.0.1:1337');//   -
  connection.onopen = function(){
//  ,  -      
 }
connection.onmessage = function(message){
//        


}
connection.onerror = function (error) {
        console.error(error)
       //  ,   
      };

So, back to our Vasya and Petya


image

This is the initial stage at which Vasya and Petya simply exchange JSON about whether we will receive a call or not. That is, when entering our page, we must open a WebSocket connection to communicate with our socket server.

  1. We first send a helmet to the JSON server socket so that we want to call Petya from Vasya’s account

    connection.send(JSON.stringify({
    //  
    }))
    
  2. We must accept this JSON on the socket server, after we receive the request, we attach the message event to our server :

    connection.on('message',function(message){
    //   message    ,     JSON  JS
    let self = JSON.parse(message.utf8Data);
    })
    

Having talked and decided that both users are ready for a conversation, we need to figure out how video communication works in a browser, a module for this is built in js - RTCPeerConnection


image

We need to open RTCPeerConnection, with which we can generate an offer and send it to the user we need, again through our socket server, which, upon receiving it, will generate a response and send it back, after which we begin to exchange ice packets containing information about the environment this computer, which is necessary for the successful establishment of video communications.

We generate and send offer


var pc = new RTCPeerConnection();
            
            var peerConnectionConfig = {
              iceServers: [
                  {
                      urls: 'stun:stun.l.google.com:19302'
                  }
                ]
            }
            pc.onicecandidate = function (event) {
              console.log('new ice candidate', event.candidate);

              if (event.candidate !== null) {
                connection.send(JSON.stringify({
                 // json  ice 
                }))
              }
          };

            navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia;
                      

            navigator.getUserMedia({video: true,audio:true}, function(stream) {
              //      onaddstream  ,
              //    .
            var my_video = document.getElementById('my')
            my_video.srcObject = stream

              pc.onaddstream = e => {
                document.getElementById('not_my').srcObject = e.stream;
                console.log('not stream is added')
              }
              pc.addStream(stream);   
            
              pc.createOffer(function(offer) {
                pc.setLocalDescription(offer, function() {
                  //  offer  
                  }))
                }, e=> console.log(e));
              }, e=> console.log(e));
            },function (){console.warn("Error getting audio stream from getUserMedia")});

            //  
            function endCall() {
              var videos = document.getElementsByTagName("video");
              for (var i = 0; i < videos.length; i++) {
                videos[i].pause();
              }
            
              pc.close();
            }

            function error(err) {
              endCall();
            }
 

We process offer and generate answer


var pc = new RTCPeerConnection();// connection
var peerConnectionConfig = { // ice server
              iceServers: [
                  {
                      urls: 'stun:stun.l.google.com:19302'
                  }
                ]
            }
            pc.onicecandidate = function (event) {
              console.log('new ice candidate', event.candidate);

              if (event.candidate !== null) {
                // ice 
              }
          };


            navigator.getUserMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia;

            navigator.getUserMedia({video: true,audio:true}, function(stream) {//          
              var my_video = document.getElementById('my')
              my_video.srcObject = stream
              console.log('stream is added while offering')

              pc.onaddstream = e => {
                console.log('not my stream is added while offering')
                document.getElementById('not_my').srcObject = e.stream;
                
              }
              pc.addStream(stream);
            
              pc.setRemoteDescription(new RTCSessionDescription(data.offer), function() {
                pc.createAnswer(function(answer) {
                  pc.setLocalDescription(answer, function() {
                    // 
                  }, e => console.log(e));
                }, e => console.log(e));
              }, e => console.log(e));
            },function (){console.warn("Error getting audio stream from getUserMedia")});
          }
        }

We accept the answer and create a video stream


pc.setRemoteDescription(new RTCSessionDescription(data.answer), function() { }, error);

And the last thing we need to do is process the ice packets


pc.addIceCandidate(new RTCIceCandidate(ice))// ice -  ,    

All Articles