(Preskaŭ) senutila retkamerao fluanta de retumilo. Parto 2. WebRTC

Iel en одной el malnovaj kaj jam forlasitaj artikoloj, mi skribis pri tio, kiel facile kaj nature oni povas elsendi filmeton el kanvaso per retejoj. En tiu artikolo, mi mallonge parolis pri kiel kapti video de fotilo kaj sono de mikrofono uzante MediaStream API, kiel kodi la ricevitan rivereton kaj sendi ĝin per retejsockets al la servilo. Tamen, fakte ili ne faras tion, por elsendoj ili uzas aŭ specialan programon, kiu devas esti instalita kaj agordita: senprokraste, ĉi tio povas esti Malfermu Elsendo Programaro, aŭ ili uzas WebRTC, kiu funkcias tuj el la skatolo, tio estas, ĝi ne postulas la instaladon de ajna kromaĵo al la flash player, kiu estos eltranĉita de la Chromium retumilo jam en decembro.

Hodiaŭ ni parolos pri WebRTC.

Reteja Realtempa Komunikado (WebRTC) ne estas ununura protokolo, ĝi estas tuta kolekto de normoj, protokoloj kaj JavaScript-APIoj, kiuj kune disponigas samul-al-kunulan realtempan video-aŭdan komunikadon, kaj ankaŭ povas esti uzata por transdoni ajnan. binaraj datumoj. Kutime retumiloj funkcias kiel samuloj, sed ĝi ankaŭ povas esti poŝtelefona aplikaĵo, ekzemple. Por organizi p2p komunikadon inter klientoj, retumilo subteno por diversaj specoj de video kaj audio kodigo necesas, subteno por diversaj retaj protokoloj, certigante la interago de aparataro kun la retumilo (per OS tavoloj): retkameraoj, sonkartoj. Ĉio ĉi tiu miksaĵo de teknologioj estas kaŝita malantaŭ la JavaScript API-abstraktado por la komforto de la programisto.

Ĉio resumas al tri API-oj:

  • MediaStream API — malmuntita lastan fojon, hodiaŭ mi skribos iom pli pri li. Servas ricevi video/aŭdiajn fluojn de la aparataro

  • RTCPeerConnection - provizas komunikadon inter du klientoj (p2p)

  • RTCDataChannel - servas por transdoni arbitrajn datumojn inter du klientoj

Preparante sonajn kaj videofluojn por transdono

Ĉio komenciĝas per "kaptado" de la retkamerao kaj mikrofonaj amaskomunikiloj. Kompreneble, krudaj fluoj ne taŭgas por organizi telekonferencon, ĉiu rivereto devas esti prilaborita: plibonigu la kvaliton, sinkronigu audion kun video, metu sinkronigajn markojn en la videofluo, kaj certigu la bitrapidecon respondan al la konstante ŝanĝiĝanta bendolarĝo de la kanalo. . La retumilo prizorgas ĉion ĉi, la programisto eĉ ne devas zorgi pri disponigado de kodado por amaskomunikiloj. Ene de moderna retumilo, jam estas programaraj tavoloj por kapti, plibonigi kvaliton (forigi eĥon kaj bruon de sono, plibonigi la bildon), video- kaj sonkodigado. La tavolskemo estas montrita en fig. 1:

(Preskaŭ) senutila retkamerao fluanta de retumilo. Parto 2. WebRTCRizo. 1. Tavoloj de audio kaj video prilaborado en la retumilo

Ĉiu prilaborado okazas rekte en la retumilo mem, sen pliaj. neniu kromaĵo bezonata. Tamen, aferoj ankoraŭ ne estas tiel rozaj por 2020. Estas retumiloj, kiuj ankoraŭ ne plene subtenas MediaStream API, vi povas sekvi la ligilon kaj vidi la kongruotabelon ĉe la fundo. IE precipe estas denove seniluziiga.

Vi povas fari tre interesajn aferojn kun la ricevitaj riveretoj: vi povas kloni, ŝanĝi la video-rezolucion, manipuli la sonkvaliton, vi povas preni kaj "alkroĉi" la Media Stream-rivereto al etikedu kaj rigardu vin sur la html-paĝo. Aŭ vi povas desegni fluon sur kanvaso, kaj agordi WebGL aŭ CSS3, kaj apliki diversajn filtrilojn al video, kapti la prilaboritan videon el kanvaso kaj poste sendi ĝin tra la reto al la servilo, transkodi kaj publikigi al ĉiuj (saluton bigo live, twitch kaj aliaj). Ĉi tie mi ne analizos kiel tiaj aferoj estas faritaj, mi donos kelkajn ekzemplojn trovitajn en la reto:

https://jeeliz.com/ - la infanoj faras realtempan CV en Javascript. Ili havas tuton arsenalo diversaj js-bibliotekoj por labori kun videofluo sur kanvaso: detekti vizaĝojn, objektojn, apliki filtrilojn (maskoj, kiel en Instagram), ktp. Bonega ekzemplo pri kiel vi povas prilabori realtempan videon rekte en la retumilo sen aldonaj kromprogramoj.

Kanvas captureStream API - API-dokumentado por kapti videofluon el kanvaso. Jam subtenata en Chrome, Opera kaj Firefox

RTCPeerConnection

Do ni venis al la afero, sed kiel efektive transdoni la videon al alia uzanto? Venas al la antaŭo RTCPeerConnection. Resume, preskaŭ ĉe ĉi tiu paŝo vi devas krei objekton RTCPeerConnection:

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

Ni specifas iceServers kiel unu el la ebloj - ĉi tiu estas servilo kiu helpas havigi konekton inter du retumiloj malantaŭ NAT'om. Tio estas, la problemo estas solvita ĉi tie: kiel ekscii la ip de la interparolanto se li estas malantaŭ la NAT de sia provizanto? La ICE-protokolo venas al la savo, fakte, ICE tute ne validas por WebRTC, sed pli pri tio poste.

Antaŭe, ni ricevis Usermedia-fluojn:

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

Poste, la evento de negotiationneeded pafas sur la peerConnection, en kies prizorganto ni devas krei oferton (laŭ SDP - Session Description Protocol) kaj asigni ĝin al la peerConnection per la setLocalDescription-metodo. Pri SDP - kio ĝi estas kaj pri la oferto kaj respondformatoj - ni parolos plu.

Post atribuado de LocalDescription peerConnection, la retumilo "kunvenas" glacikandidatojn, tio estas, trovas diversajn manierojn komuniki per NAT. La unuonicegatheringstatechange-okazaĵo pafas. En la pritraktilo onicegatheringstatechange, ni permesas konekton al la webrtc-signaling-server-rivereto interŝanĝi la Seanca Priskribon inter samuloj:

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

La webrtc-signaling-server estas la servilo postulata por interŝanĝi la seanpriskribon inter du samuloj, ĝi povas esti la plej simpla retsocket aŭ xhr-servilo sur iu PL. Ĝia tasko estas simpla: akcepti seancan priskribon de unu samaĝulo kaj transdoni ĝin al alia.

Post la interŝanĝo de Sesiaj priskriboj, ambaŭ flankoj pretas elsendi kaj ricevi videofluojn, ĉe la flanko, kiu ricevas la videofluon, la onttrack-evento estas ekigita sur la peerConnection, en kies prizorganto, la ricevitaj trakoj povas esti asignitaj al kaj rigardu vian plej ŝatatan interparolanton. Plia teorio kaj detaloj.

Ligiloj kaj literaturo:

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

https://github.com/pion/webrtc - efektivigo de WebRTC-protokoloj survoje

https://webrtcforthecurious.com/ - libro de la kreintoj de pion

https://hpbn.co/ - Book High Performance Folium Networking. La aferoj pri certigo de alta rendimento de TTT-aplikoj estas detale diskutitaj. Ĉe la fino, WebRTC estas priskribita. La libro certe estas malnova (2013), sed ne perdas sian gravecon.

En la sekva parto, mi volas doni iom pli da teorio kaj praktike analizi la ricevon kaj prilaboradon de videofluo en la servilo uzante pion, transkodi al HLS per ffmpeg por posta elsendo al spektantoj en la retumilo.

Por senpacienculoj: mia tre kruda prototipo de dissendado de video de retkamerao por reagi per pion-bazita servilo en twitch (ĉi tio estas nur eksperimento).

fonto: www.habr.com

Aldoni komenton