WebRTC Fazendo um aplicativo com blackjack e videochamadas

Caro leitor, antes de começarmos a escrever o código, vamos dar uma olhada no conceito de vídeo chamadas.

Imagine a situação: temos uma plataforma de bate-papo e precisamos anexar videochamadas, ou seja, um certo Vasya está sentado online e ele quer ligar para Petya, para implementar esse recurso, precisamos da tecnologia WebSocket .

Bem, vamos aumentar nosso servidor WebSocket, o node.js nos ajudará com isso;
Crie o arquivo sockets.js e escreva o código do soquete do servidor:

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);
//   
})

Crie um arquivo index.html e escreva o código para abrir uma conexão de soquete:

     <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> <!--  -->

Agora crie e conecte o arquivo script.js ao nosso arquivo html:

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


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

Então, de volta aos nossos Vasya e Petya


imagem

Esse é o estágio inicial no qual Vasya e Petya simplesmente trocam JSON sobre a possibilidade de recebermos uma chamada ou não, ou seja, ao entrar em nossa página, precisamos abrir uma conexão WebSocket para se comunicar com nosso servidor de soquete.

  1. Primeiro enviamos um capacete para o soquete do servidor JSON, para que desejemos ligar para Petya da conta de Vasya

    connection.send(JSON.stringify({
    //  
    }))
    
  2. Devemos aceitar esse JSON no servidor de soquete. Após recebermos a solicitação, anexamos o evento de mensagem ao nosso servidor :

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

Depois de conversar e decidir que os dois usuários estão prontos para uma conversa, precisamos descobrir como a comunicação por vídeo funciona em um navegador, um módulo para isso é construído em js - RTCPeerConnection


imagem

Precisamos abrir o RTCPeerConnection, com o qual podemos gerar uma oferta e enviá-la ao usuário de que precisamos, novamente através do nosso servidor de soquete, que, ao recebê-la, gerará uma resposta e a enviará de volta, após o que começamos a trocar pacotes de gelo contendo informações sobre o ambiente este computador, necessário para o estabelecimento bem-sucedido de comunicações de vídeo.

Geramos e enviamos ofertas


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();
            }
 

Processamos ofertas e geramos respostas


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")});
          }
        }

Aceitamos a resposta e criamos um fluxo de vídeo


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

E a última coisa que precisamos fazer é processar os pacotes de gelo


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

All Articles