(Gati) transmetimi i panevojshëm i kamerës nga shfletuesi. Pjesa 2. WebRTC

Njëherë një në disa artikuj të vjetër dhe tashmë të braktisur, kam shkruar se sa lehtë dhe pa ndonjë vështirësi mund të transmetoni video nga canvas përmes websockets. Në atë artikull, fola në mënyrë të përgjithshme se si të kapësh video nga kamera dhe audio nga mikrofoni duke përdorur MediaStream API, si të kodoni dhe dërgoni këtë rrjedhë përmes websockets në server. Megjithatë, në realitet, kjo nuk bëhet, për transmetime përdoren ose softuer të veçantë që duhet instaluar dhe konfiguruar: për të thënë në mënyrë të rastësishme, mund të jetë Open Broadcast Software, ose përdorin WebRTC, i cili funksionon direkt nga kutia, që do të thotë se nuk kërkon instalimin e ndonjë plugin-i siç është flash player, i cili do të hiqet nga shfletuesi Chromium në dhjetor.

Sot do të flasim për WebRTC.

Web Real-Time Communication (WebRTC) nuk është një protokoll i vetëm; është një koleksion standardesh, protokollesh dhe JavaScript API, të cilat së bashku ofrojnë komunikime video-audio në kohë reale nga peer në peer, dhe gjithashtu mund të përdoren për transferimin e çdo lloj të dhënash binare. Zakonisht, browser-at janë partnerët, por gjithashtu mund të jetë një aplikacion mobil, për shembull. Për të organizuar komunikimin p2p midis klientëve, kërkohet mbështetje nga shfletuesi për forma të ndryshme të kodimit të videos dhe audios, mbështetje për shumë protokolle rrjetimi, si dhe sigurimi i ndërveprimit të harduerit me shfletuesin (përmes shtresave të OS): kamera web, karta audio. Të gjitha këto teknologji janë fshehur pas një abstraksioni JavaScript API për lehtësinë e zhvilluesve.

Në fund, gjithçka reduktohet në tre API:

  • MediaStream API — e kemi diskutuar herën e kaluar, sot do të shkruaj pak më shumë për të. Shërben për marrjen e rrjedhave video/audio nga "hardueri"

  • RTCPeerConnection — siguron komunikim midis dy klientëve (p2p)

  • RTCDataChannel — shërben për transferimin e të dhënave arbitrare midis dy klientëve

Përgatitja e rrjedhave audio dhe video për transmetim

Gjithçka fillon me "kapjen" e rrjedhave mediatike nga kamera dhe mikrofoni. Rrjedhat e papërpunuara natyrisht që nuk janë të përshtatshme për organizimin e telekonferencave, çdo rrjedhë duhet të përpunohet: të përmirësohet cilësia, të sinkronizohet audio me videon, të vendosen etiketa sinkronizimi në videostream, të sigurohet që bitrate përputhet vazhdimisht me gjerësinë e kalimit të kanaleve. Shfletuesi merr përsipër gjithçka, zhvilluesi madje nuk duhet të shqetësohet për sigurimin e kodimit të rrjedhave mediatike. Brenda shfletuesve modernë, tashmë ekzistojnë shtresat programore të kapjes, përmirësimit të cilësisë (për të hequr jehonën dhe zhurmën nga zëri, për të përmirësuar pamjen), për kodimin e videos dhe audios. Schema e shtresave është e ilustruar në Fig. 1:

(Gati) transmetimi i panevojshëm i kamerës nga shfletuesi. Pjesa 2. WebRTCFig. 1. Shtresat e përpunimit të audios dhe videos në shfletues

E gjithë përpunimi ndodh direkt brenda shfletuesit, nuk kërkohen plugina të tjerë. Megjithatë, asgjë nuk është aq e bukur në vitin 2020. Ka shfletues që akoma nuk mbështesin plotësisht MediaStream API, mund të shkoni në lidhje dhe në fund të faqes të shikoni tabelën e përputhshmërisë. Në veçanti, IE përsëri zhgënjen.

Me rrjedhat e marra mund të bëni gjëra shumë interesante: mund të klononi, të ndryshoni përmasat e videos, të manipuloni cilësinë e audios, mund të merrni dhe "të kapni" rrjedhën e Media Stream në tagun <video> dhe të shikoni veten tuaj të dashur në faqen html. Ose mund të vizatoni rrjedhën në canvas, ta drejtoni në WebGL ose CSS3, dhe të vendosni efekte të ndryshme në video, të kapni videon e përpunuar nga canvas dhe më pas ta dërgoni në rrjet në server për ta transkoduar dhe publikuar për të gjithë ata që duan (përshëndetje bigo live, twitch dhe të tjerët). Këtu nuk do të shpjegoj sesi bëhen këto gjëra, do të sjell disa shembuj, të gjetur në hapësirën e internetit:

https://jeeliz.com/ — djemtë po punojnë me CV në kohë reale në Javascript. Ata kanë një arsenal të ndryshme bibliotekash js për të punuar me videostream në canvas: identifikimi i fytyrave, objekteve, vendosja e efekteve (maskat, si në Instagram) etj. Një shembull i shkëlqyer se si pa plugina të tjera, mund të verarbeitet video në kohë reale direkt në shfletues.

Canvas captureStream API — dokumentacioni i API për kapjen e videostream nga canvas. Tashmë mbështetet në Chrome, Opera dhe Firefox.

RTCPeerConnection

Këtu arrijmë te pyetja, si mund ta dërgojmë videon te një përdorues tjetër? Në planin e parë del RTCPeerConnection. Nëse flasim shkurt, pothuajse në këtë hap, ju nevojitet të krijoni një objekt RTCPeerConnection:

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

Një nga opsionet është që të tregoni iceServers — ky është një server që ndihmon në sigurimin e lidhjes midis dy shfletuesve që ndodhen pas NAT-it. Kjo do të thotë se këtu zgjidhet problemi: si të dish IP-në e personit me të cilin bisedon, nëse ai ndodhet pas NAT-it të ofruesit të tij? Për këtë ndihmon protokolli ICE, në të vërtetë, ICE nuk i përket WebRTC, por për këtë më vonë.

Më parë, kemi marrë rrjedhat e Usermedia:

navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
  // Kanalet e Usermedia, zakonisht video dhe audio 
  const tracks = stream.getTracks();

   for (const track of tracks) {
     // secili kanal i bashkëngjitet peerConnection
     peerConnection.addTrack(track);
   }
}).catch(console.error);

Më pas në peerConnection ndodh ngjarja onnegotiationneeded, në trajtimin e së cilës ne duhet të krijojmë një ofertë (në terminologjinë SDP — Protokolli i Përshkrimit të Sesionit) dhe ta caktojmë në peerConnection përmes metodës setLocalDescription. Në lidhje me SDP — çfarë është dhe formato e ofertës dhe përgjigjes — do të flasim më vonë.

Pas caktimit të LocalDescription në peerConnection, shfletuesi "mbledh" kandidatë ice, domethënë gjen mënyra të ndryshme për komunikimin përmes NAT. Ndodh ngjarja onicegatheringstatechange. Në trajtuesin onicegatheringstatechange lejojmë lidhjen me serverin webrtc-signaling për shkëmbimin e Përshkrimi të Sesionit mes dy njerëzve:

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

serveri webrtc-signaling — është një server i nevojshëm për të siguruar shkëmbimin e përshkrimeve të sesionit mes dy palëve, mund të jetë një server websocket i thjeshtë ose xhr në ndonjë gjuhë programimi. Detyra e tij është e thjeshtë: të pranojë përshkrimin e sesionit nga një palë dhe ta transmetojë tek tjetra.

Pas shkëmbimit të Përshkrimeve të Sesionit, të dy palët janë gati për të transmetuar dhe pranuar rrjedhat video, në anën që pranon rrjedhën video ndodh ngjarja ontrack në peerConnection, në trajtuesin e saj, kanalet e marra mund të caktohen në

Lidhjet dhe literatura:

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

https://github.com/pion/webrtc — implementimi i protokolleve WebRTC në go

https://webrtcforthecurious.com/ — një libër nga krijuesit e pion

https://hpbn.co/ — libri High Performance Browser Networking. Detaje në lidhje me sigurimin e performancës së lartë për aplikacionet web. Në fund trajtohet WebRTC. Libri është sigurisht i vjetër (2013), por nuk humbet aktualitetin e tij.

Në pjesën tjetër dua të ofroj disa teori dhe në praktikë të shqyrtoj pranim dhe trajtimin e rrjedhës video në server me ndihmën e pion, transkodimin në HLS përmes ffmpeg për transmetimin e mëvonshëm te shikuesit në shfletues.

Për të padurueshmit: prototipi im shumë i papërpunuar i transmetimit të videos nga kamera në react përmes një serveri të bazuar në pion në twitch (kjo është thjesht një eksperiment).

Burimi: habr.com

Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS 🔥 Bleni hostim të besueshëm për faqe me mbrojtje nga DDoS, serverë VPS VDS | ProHoster