(Melkein) turha verkkokameran suoratoisto selaimesta. Osa 2. WebRTC

Jotenkin sisään одной vanhoista ja jo hylätyistä artikkeleista kirjoitin siitä, kuinka helposti ja luonnollisesti voit lähettää videota kankaasta verkkoliitäntöjen kautta. Tuossa artikkelissa puhuin lyhyesti videon kaappaamisesta kamerasta ja äänen mikrofonista käyttämällä MediaStream API, kuinka vastaanotettu virta koodataan ja lähetetään websockettien kautta palvelimelle. Todellisuudessa he eivät kuitenkaan tee tätä, vaan he käyttävät lähetyksiä varten joko erityistä ohjelmistoa, joka on asennettava ja määritettävä: tämä voi olla suoraan Avaa lähetysohjelmisto, tai he käyttävät WebRTC:tä, joka toimii suoraan pakkauksesta, eli se ei vaadi lisäosien asentamista a la flash playeriin, joka leikataan pois Chromium-selaimesta jo joulukuussa.

Tänään puhumme WebRTC:stä.

Web Real-Time Communication (WebRTC) ei ole yksittäinen protokolla, se on koko kokoelma standardeja, protokollia ja JavaScript-sovellusliittymiä, jotka yhdessä tarjoavat peer-to-peer reaaliaikaista video-ääniviestintää ja joita voidaan käyttää myös minkä tahansa tiedon siirtämiseen. binääridataa. Yleensä selaimet toimivat vertaisina, mutta se voi olla myös esimerkiksi mobiilisovellus. Asiakkaiden välisen p2p-viestinnän järjestämiseksi tarvitaan selaintuki erityyppisille video- ja äänikoodauksille, tuki erilaisille verkkoprotokolloille, mikä varmistaa laitteiston vuorovaikutuksen selaimen kanssa (käyttöjärjestelmäkerrosten kautta): web-kamerat, äänikortit. Kaikki tämä teknologioiden sekamelska on piilotettu JavaScript API -abstraktsioonin taakse kehittäjän avuksi.

Kaikki tiivistyy kolmeen sovellusliittymään:

  • MediaStream API — purettu viimeksi, tänään kirjoitan hänestä hieman enemmän. Vastaanottaa video-/äänivirtoja laitteistosta

  • RTCPeerConnection - tarjoaa viestintää kahden asiakkaan välillä (p2p)

  • RTCDataChannel - palvelee mielivaltaisten tietojen siirtämistä kahden asiakkaan välillä

Valmistelee ääni- ja videovirtoja lähetystä varten

Kaikki alkaa web-kameran ja mikrofonin mediavirran "kaappaamisesta". Raaka-streamit eivät tietenkään sovi puhelinkonferenssin järjestämiseen, jokainen stream on käsiteltävä: parantaa laatua, synkronoida ääni videon kanssa, sijoittaa synkronointimerkit videovirtaan ja varmistaa kanavan jatkuvasti muuttuvaa kaistanleveyttä vastaava bittinopeus. . Selain huolehtii kaikesta tästä, kehittäjän ei tarvitse edes huolehtia koodauksen tarjoamisesta mediavirroille. Nykyaikaisen selaimen sisällä on jo ohjelmistokerroksia kaappaamiseen, laadun parantamiseen (poista kaiku ja kohina äänestä, paranna kuvaa), videon ja äänen koodausta. Kerroskaavio on esitetty kuvassa. 1:

(Melkein) turha verkkokameran suoratoisto selaimesta. Osa 2. WebRTCRiisi. 1. Äänen ja videon käsittelyn kerrokset selaimessa

Kaikki käsittely tapahtuu suoraan selaimessa, ei ylimääräisiä. lisäosia ei tarvita. Asiat eivät kuitenkaan ole vielä niin ruusuisia vuodelle 2020. On selaimia, jotka eivät vielä täysin tue MediaStream API, voit seurata linkkiä ja nähdä yhteensopivuustaulukon aivan alareunassa. Etenkin IE on jälleen pettymys.

Vastaanotetuilla virroilla voi tehdä erittäin mielenkiintoisia asioita: voit kloonata, muuttaa videon resoluutiota, manipuloida äänenlaatua, ottaa Media Stream -striimin "koukkuun" tagi ja katso itseäsi html-sivulla. Tai voit piirtää streamin kankaalle ja asettaa WebGL:n tai CSS3:n ja käyttää erilaisia ​​suodattimia videoon, kaapata käsitellyn videon kankaasta ja lähettää sen sitten verkon kautta palvelimelle, transkoodata ja julkaista kaikille (hello bigo live, twitch ja muut). Tässä en analysoi, kuinka tällaiset asiat tehdään, annan pari verkosta löytyvää esimerkkiä:

https://jeeliz.com/ - kaverit tekevät reaaliaikaista CV:tä Javascriptillä. Heillä on kokonaisuus arsenaali erilaisia ​​js-kirjastoja työskentelyyn videovirran kanssa kankaalla: kasvojen, esineiden havaitseminen, suodattimien (naamarit, kuten Instagramissa) käyttäminen jne. Erinomainen esimerkki siitä, kuinka voit käsitellä reaaliaikaista videota suoraan selaimessa ilman lisälaajennuksia.

Canvas captureStream API - API-dokumentaatio videovirran kaappaamiseen kankaalta. Tuettu jo Chromessa, Operassa ja Firefoxissa

RTCPeerConnection

Joten tulimme asiaan, mutta kuinka siirtää video toiselle käyttäjälle? Tulee etualalle RTCPeerConnection. Lyhyesti sanottuna, melkein tässä vaiheessa sinun on luotava RTCPeerConnection-objekti:

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

Määritämme yhdeksi vaihtoehdoksi iceServersin - tämä on palvelin, joka auttaa tarjoamaan yhteyden kahden selaimen välillä NAT'omin takana. Eli ongelma on ratkaistu täällä: kuinka saada selville keskustelukumppanin IP, jos hän on palveluntarjoajansa NAT:n takana? ICE-protokolla tulee apuun, itse asiassa ICE ei koske WebRTC:tä ollenkaan, mutta siitä lisää myöhemmin.

Aiemmin meillä on Usermedia-streamit:

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

Seuraavaksi onnegotiationneeded -tapahtuma käynnistyy peerConnectionissa, jonka käsittelijässä meidän on luotava tarjous (SDP:n kannalta - Session Description Protocol) ja osoitettava se peerConnectionille setLocalDescription-metodilla. SDP:stä - mitä se on ja tarjouksista ja vastausmuodoista - puhumme lisää.

Kun LocalDescription-peerConnection on määritetty, selain "kokoaa" jääehdokkaat, eli löytää erilaisia ​​tapoja kommunikoida NAT:n kautta. Onicegatheringstatechange -tapahtuma syttyy. Onicegatheringstatechange-käsittelijässä sallimme yhteyden webrtc-signaling-server-virtaan istunnon kuvauksen vaihtamiseksi vertaisten välillä:

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

Webrtc-signaling-server on palvelin, jota tarvitaan istunnon kuvauksen vaihtamiseen kahden vertaisen välillä, se voi olla minkä tahansa PL:n yksinkertaisin websocket tai xhr-palvelin. Sen tehtävä on yksinkertainen: hyväksyä istunnon kuvaus yhdeltä vertaiselta ja siirtää se toiselle.

Session-kuvausten vaihdon jälkeen molemmat osapuolet ovat valmiita lähettämään ja vastaanottamaan videovirtoja, videovirran vastaanottavalla puolella ontrack-tapahtuma laukeaa peerConnectionissa, jonka käsittelijässä vastaanotetut raidat voidaan määrittää ja katso suosikkikeskustelukumppaniasi. Lisää teoriaa ja yksityiskohtia.

Linkkejä ja kirjallisuutta:

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

https://github.com/pion/webrtc - WebRTC-protokollien käyttöönotto liikkeellä

https://webrtcforthecurious.com/ - kirja pionin tekijöiltä

https://hpbn.co/ - Varaa suorituskykyinen selainverkko. Verkkosovellusten korkean suorituskyvyn varmistamiseen liittyviä kysymyksiä käsitellään yksityiskohtaisesti. Lopussa kuvataan WebRTC. Kirja on varmasti vanha (2013), mutta ei menetä merkitystään.

Seuraavassa osassa haluan antaa hieman enemmän teoriaa ja käytännössä analysoida videovirran vastaanottoa ja käsittelyä palvelimella pionin avulla, transkoodaamalla HLS:ksi ffmpeg:n kautta myöhempää lähetystä varten katsojille selaimessa.

Kärsimättömille: erittäin karkea prototyyppini videon lähettämisestä web-kamerasta, joka reagoi pionipohjaisen palvelimen kautta nykimiseen (tämä on vain kokeilu).

Lähde: will.com

Lisää kommentti