(Case) inútil transmisión de webcam desde un navegador. Parte 2. WebRTC

Dalgún xeito dentro un a partir de artigos antigos e xa abandonados, escribín sobre a facilidade e naturalidade que pode transmitir o vídeo desde o lenzo a través de websockets. Nese artigo, falei brevemente sobre como capturar vídeo dunha cámara e son dun micrófono usando API MediaStream, como codificar o fluxo recibido e envialo a través de websockets ao servidor. Non obstante, en realidade non o fan, para as emisións usan un software especial que hai que instalar e configurar. Abra o software de difusión, ou usan WebRTC, que funciona desde o primeiro momento, é dicir, non require a instalación de ningún complemento como o flash player, que se cortará do navegador Chromium xa en decembro.

Hoxe falaremos de WebRTC.

A comunicación en tempo real web (WebRTC) non é un protocolo único, é unha colección completa de estándares, protocolos e API de JavaScript que, xuntos, proporcionan comunicación de vídeo e audio en tempo real entre pares e tamén se poden usar para transferir calquera datos binarios. Normalmente os navegadores actúan como pares, pero tamén pode ser unha aplicación móbil, por exemplo. Para organizar a comunicación p2p entre clientes, requírese soporte do navegador para varios tipos de codificación de vídeo e audio, soporte para unha variedade de protocolos de rede, garantindo a interacción do hardware co navegador (a través de capas do sistema operativo): cámaras web, tarxetas de son. Toda esta mezcolanza de tecnoloxías escóndese detrás da abstracción da API de JavaScript para a comodidade do programador.

Todo se reduce a tres API:

  • API MediaStream — desmontado a última vez, hoxe escribirei un pouco máis sobre el. Serve para recibir fluxos de vídeo/audio do hardware

  • Conexión RTCPeer - proporciona comunicación entre dous clientes (p2p)

  • RTCDataChannel - serve para transferir datos arbitrarios entre dous clientes

Preparación de fluxos de audio e vídeo para a súa transmisión

Todo comeza coa "captura" dos fluxos multimedia da cámara web e do micrófono. Por suposto, os fluxos en bruto non son axeitados para organizar unha teleconferencia, cada fluxo debe ser procesado: mellorar a calidade, sincronizar o audio co vídeo, colocar marcas de sincronización no fluxo de vídeo e garantir a taxa de bits correspondente ao ancho de banda en constante cambio da canle. . O navegador encárgase de todo isto, o programador nin sequera ten que preocuparse por proporcionar codificación para fluxos multimedia. Dentro dun navegador moderno, xa hai capas de software para capturar, mellorar a calidade (eliminar o eco e o ruído do son, mellorar a imaxe), a codificación de vídeo e audio. O esquema de capas móstrase na fig. 1:

(Case) inútil transmisión de webcam desde un navegador. Parte 2. WebRTCArroz. 1. Capas de procesamento de audio e vídeo no navegador

Todo o procesamento realízase directamente no propio navegador, sen adicional. non se necesitan complementos. Non obstante, as cousas aínda non están tan bos para 2020. Hai navegadores que aínda non son totalmente compatibles API MediaStream, podes seguir a ligazón e ver a táboa de compatibilidade na parte inferior. IE en particular volve ser decepcionante.

Podes facer cousas moi interesantes coas emisións recibidas: podes clonar, cambiar a resolución do vídeo, manipular a calidade do audio, podes coller e "enganchar" a emisión de Media Stream a etiqueta e mira a ti mesmo na páxina html. Ou pode debuxar un fluxo no lenzo e configurar WebGL ou CSS3 e aplicar varios filtros ao vídeo, capturar o vídeo procesado do lenzo e despois envialo pola rede ao servidor, transcodificalo e publicalo para todos (hola bigo live, twitch e outros). Aquí non vou analizar como se fan tales cousas, vou poñer un par de exemplos atopados na web:

https://jeeliz.com/ - Os rapaces están facendo un CV en tempo real en Javascript. Teñen un todo arsenal varias bibliotecas js para traballar cun fluxo de vídeo no lenzo: detectar caras, obxectos, aplicar filtros (máscaras, como en Instagram), etc. Un excelente exemplo de como pode procesar vídeo en tempo real directamente no navegador sen complementos adicionais.

Canvas captureStream API - Documentación da API para capturar un fluxo de vídeo desde o lenzo. Xa é compatible con Chrome, Opera e Firefox

Conexión RTCPeer

Entón chegamos ao grano, pero como transferir realmente o vídeo a outro usuario? Vén a primeiro plano Conexión RTCPeer. En resumo, case neste paso necesitas crear un obxecto RTCPeerConnection:

const peerConnection = new RTCPeerConnection({
  iceServers: [{
    urls: 'stun:stun.l.google.com:19302'
  }]
});

Especificamos iceServers como unha das opcións: este é un servidor que axuda a proporcionar unha conexión entre dous navegadores detrás de NAT'om. É dicir, o problema resólvese aquí: como saber a ip do interlocutor se está detrás do NAT do seu provedor? O protocolo ICE vén ao rescate, de feito, ICE non se aplica a WebRTC en absoluto, pero sobre iso máis tarde.

Anteriormente, tiñamos emisións de Usermedia:

navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
  // Usermedia-потоки, обычно это видео и аудио 
  const tracks = stream.getTracks();

   for (const track of tracks) {
     // каждый трек присоединяем к peerConnection
     peerConnection.addTrack(track);
   }
}).catch(console.error);

A continuación, o evento onnegotiationneeded desenvólvese no peerConnection, en cuxo controlador debemos crear unha oferta (en termos de SDP - Session Description Protocol) e asignala ao peerConnection mediante o método setLocalDescription. Sobre SDP - o que é e sobre os formatos de oferta e resposta - falaremos máis.

Despois de asignar unha LocalDescription peerConnection, o navegador "recolle" candidatos de xeo, é dicir, atopa varias formas de comunicarse a través de NAT. O evento onicegatheringstatechange desenvólvese. No manejador onicegatheringstatechange, permitimos unha conexión ao fluxo webrtc-signaling-server para intercambiar a descrición da sesión entre pares:

peerConnection.oniceconnectionstatechange = (event) => {
      console.log('Connection state: ', peerConnection.iceConnectionState);

      if (peerConnection.iceConnectionState === 'connected') {
        // Можем активировать кнопку Start broadcast
        setBroadcasting(true);
        setBroadcastingBtnActive(true);
      }
    };

// Событие срабатывает сразу, как только добавился медаиапоток в peerConnection
peerConnection.onnegotiationneeded = (event) => {
      // Создаем и назначаем SDP offer
      peerConnection.createOffer().
        then((offer) => peerConnection.setLocalDescription(offer)).
        catch(console.error);
    };

// Событие срабатывает каждый раз, как появляется ICE кандидат
peerConnection.onicegatheringstatechange = (ev) => {
      let connection = ev.target;

      // Now we can activate broadcast button
      if (connection.iceGatheringState === 'complete') {
        let delay = 50;
        let tries = 0;
        let maxTries = 3;

        let timerId = setTimeout(function allowStreaming() {
          if (isOnline) {
            setBroadcastingBtnActive(true);
            return;
          }

          if (tries < maxTries) {
            tries += 1;
            delay *= 2;
            timerId = setTimeout(allowStreaming, delay);
          } else {
            // TODO: show user notification
            console.error("Can't connect to server");

            alert("Can't connect to server");
          }
        }, delay);
      }
    };

O servidor webrtc-signaling-server é o servidor necesario para intercambiar a descrición da sesión entre dous pares, pode ser o websocket ou xhr-server máis sinxelo de calquera PL. A súa tarefa é sinxela: aceptar unha descrición da sesión dun compañeiro e transferila a outro.

Despois do intercambio de descricións da sesión, ambos os dous lados están listos para transmitir e recibir fluxos de vídeo, no lado que recibe o fluxo de vídeo, o evento onttrack desenvólvese no peerConnection, cuxo controlador pódense asignar as pistas recibidas a e mira o teu interlocutor favorito. Máis teoría e detalles.

Ligazóns e literatura:

https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection - documentación Conexión RTCPeer

https://github.com/pion/webrtc - Implementación de protocolos WebRTC en marcha

https://webrtcforthecurious.com/ - un libro dos creadores de pion

https://hpbn.co/ - Reserva de redes de navegador de alto rendemento. Os problemas de garantir un alto rendemento das aplicacións web son discutidos en detalle. Ao final, descríbese WebRTC. O libro é certamente antigo (2013), pero non perde a súa relevancia.

Na seguinte parte, quero dar un pouco máis de teoría e na práctica analizar a recepción e procesamento dun fluxo de vídeo no servidor mediante pion, transcodificando a HLS a través de ffmpeg para a súa posterior emisión aos espectadores no navegador.

Para os impacientes: o meu prototipo moi tosco de transmisión de vídeo desde unha cámara web para reaccionar a través dun servidor baseado en pion en Twitch (isto é só un experimento).

Fonte: www.habr.com

Compre hospedaxe fiable para sitios con protección DDoS, servidores VPS VDS 🔥 Compra aloxamento web fiable con protección DDoS, servidores VPS VDS | ProHoster