(Quasi) inutilità webcam streaming da un navigatore. Parte 2. WebRTC

In qualchì modu in unu da articuli vechji è digià abbandunati, aghju scrittu annantu à quantu facilmente è naturalmente pudete trasmette video da tela via websockets. In quellu articulu, aghju brevemente parlatu di cumu catturà video da una camera è u sonu da un micru utilizendu API MediaStream, cumu codificà u flussu ricevutu è mandà via websockets à u servitore. In ogni casu, in realtà ùn facenu micca questu, per i broadcasts usanu sia un software speciale chì deve esse stallatu è cunfiguratu: offhand, questu pò esse Software Open Broadcast, o usanu WebRTC, chì travaglia ghjustu fora di a scatula, vale à dì, ùn hè micca bisognu di a stallazione di ogni plugins à la flash player, chì sarà cutatu fora di u navigatore Chromium digià in dicembre.

Oghje parlemu di WebRTC.

A Comunicazione Web Real-Time (WebRTC) ùn hè micca un protokollu unicu, hè una cullizzioni sana di standard, protokolli è API JavaScript chì inseme furnisce una cumunicazione video-audio peer-to-peer in tempu reale, è pò ancu esse aduprata per trasferisce qualsiasi dati binari. Di solitu i navigatori agiscenu cum'è pari, ma pò ancu esse una applicazione mobile, per esempiu. Per urganizà a cumunicazione p2p trà i clienti, u supportu di u navigatore per vari tipi di codificazione video è audio hè necessariu, supportu per una varietà di protokolli di rete, assicurendu l'interazzione di hardware cù u navigatore (per mezu di strati OS): webcams, carte sonu. Tuttu stu mischju di tecnulugia hè oculatu daretu à l'astrazione di l'API JavaScript per a cunvenzione di u sviluppatore.

Tuttu si riduce à trè API:

  • API MediaStream — smontatu l'ultima volta, oghje scriveraghju un pocu di più nantu à ellu. Serve per riceve flussi video / audio da u hardware

  • RTCPeerConnection - furnisce a cumunicazione trà dui clienti (p2p)

  • RTCDataChannel - serve à trasfiriri dati arbitrariu trà dui clienti

Preparazione di flussi audio è video per a trasmissione

Tuttu principia cù "catturà" a webcam è i flussi media di u microfonu. Di sicuru, i flussi crudi ùn sò micca adattati per urganizà una teleconferenza, ogni flussu deve esse processatu: migliurà a qualità, sincronizà l'audio cù u video, mette i marchi di sincronizazione in u flussu di video, è assicuratevi u bitrate chì currisponde à a larghezza di banda in constantemente cambiante di u canali. . U navigatore si cura di tuttu questu, u sviluppatore ùn hà mancu a preoccupazione di furnisce codificazione per i flussi media. Dentru un navigatore mudernu, ci sò digià strati di software per catturà, migliurà a qualità (sguassate l'eco è u rumore da u sonu, migliurà a stampa), codificazione di video è audio. U schema di strati hè mostratu in a fig. 1:

(Quasi) inutilità webcam streaming da un navigatore. Parte 2. WebRTCRisu. 1. Capi di trasfurmazioni audio è video in u navigatore

Tutti i prucessi sò fatti direttamente in u navigatore stessu, senza supplementu. ùn hè micca necessariu plugins. Tuttavia, e cose ùn sò micca cusì rosa per u 2020. Ci sò navigatori chì ùn anu micca ancu supportu cumplettamente API MediaStream, pudete seguità u ligame è vede a tavola di cumpatibilità in u fondu. IE in particulare hè di novu deludente.

Pudete fà cose assai interessanti cù i flussi ricevuti: pudete clone, cambià a risuluzione di u video, manipule a qualità audio, pudete piglià è "attaccate" u flussu Media Stream à tag è fighjate nantu à a pagina html. O pudete disegnà un flussu nantu à canvas, è stabilisce WebGL o CSS3, è applicà diversi filtri à u video, catturà u video processatu da u canvas è poi mandatu nantu à a reta à u servitore, trascodificà è publicà à tutti (ciao bigo live, twitch è altri). Quì ùn aghju micca analizà cumu si facenu tali cose, daraghju un paru di esempi truvati in u web:

https://jeeliz.com/ - i ragazzi facenu un CV in tempu reale in Javascript. Hanu un sanu arsenale diverse biblioteche js per travaglià cù un flussu di video nantu à tela: deteczione di facce, oggetti, applicà filtri (maschere, cum'è in Instagram), etc. Un esempiu eccellente di cumu pudete processà video in tempu reale direttamente in u navigatore senza plugins supplementari.

Canvas captureStream API - Documentazione API per catturà un flussu video da u canvas. Dighjà supportatu in Chrome, Opera è Firefox

RTCPeerConnection

Allora avemu ghjuntu à u puntu, ma cumu trasfiriri veramente u video à un altru utilizatore? Veni in prima RTCPeerConnection. In corta, à quasi stu passu avete bisognu di creà un oggettu RTCPeerConnection:

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

Specificemu iceServers cum'è una di l'opzioni - questu hè un servitore chì aiuta à furnisce una cunnessione trà dui navigatori daretu à NAT. Questu hè, u prublema hè risolta quì: cumu truvà l'ip di l'interlocutore s'ellu hè daretu à u NAT di u so fornitore? U protocolu ICE vene in salvezza, in fattu, ICE ùn hè micca applicatu à WebRTC in tuttu, ma più nantu à questu dopu.

Prima, avemu avutu u flussu 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);

In seguitu, l'avvenimentu onnegotiationneeded spara nantu à u peerConnection, in u gestore di quale avemu da creà una offerta (in termini di SDP - Session Description Protocol) è l'assignà à u peerConnection via u metudu setLocalDescription. À propositu di SDP - ciò chì hè è nantu à i formati di l'offerta è di a risposta - parlemu più.

Dopu l'assignazione di una LocalDescription peerConnection, u navigatore "college" candidati di ghiaccio, vale à dì, trova diverse manere di cumunicà attraversu NAT. L'avvenimentu di u cambiamentu di u statu di una riunione spara. In u gestore di onicegatheringstatechange, permettemu una cunnessione à u flussu webrtc-signaling-server per scambià a Session Description trà i pari:

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

U webrtc-signaling-server hè u servitore necessariu per scambià a descrizzione di a sessione trà dui pari, pò esse u websocket più simplice o xhr-server in ogni PL. U so compitu hè simplice: accettà una descrizzione di sessione da un paru è trasferisce à un altru.

Dopu à u scambiu di e descrizzioni di a sessione, i dui lati sò pronti à trasmette è riceve flussi video, da u latu chì riceve u flussu video, l'avvenimentu onttrack hè attivatu nantu à u peerConnection, in u gestore di quale, e tracce ricevute ponu esse assignate à è fighjate à u vostru interlocutore preferitu. Ulteriori teoria è dettagli.

Ligami è letteratura:

https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection - documentazione RTCPeerConnection

https://github.com/pion/webrtc - implementazione di protokolli WebRTC in viaghju

https://webrtcforthecurious.com/ - un libru da i creatori di pione

https://hpbn.co/ - Libru Rete di Browser High Performance. I prublemi di assicurà un altu rendimentu di l'applicazioni web sò discututi in dettaglio. À a fine, WebRTC hè descrittu. U libru hè certamente vechju (2013), ma ùn perde micca a so rilevanza.

In a parti dopu, vogliu dà un pocu più parte di a teoria è, in pratica, analizà a ricezione è u processu di un flussu di video nantu à u servitore usendu pion, trascodificà à HLS via ffmpeg per a trasmissione successiva à i televidenti in u navigatore.

Per l'impatiente: u mo prototipu assai crudu di trasmissione video da una webcam per reagisce via un servitore basatu in pioni in twitch (questu hè solu un esperimentu).

Source: www.habr.com

Add a comment