(Gandrīz) bezjēdzīga tīmekļa kameras straumēšana no pārlūkprogrammas. 2. daļa. WebRTC

Kaut kā iekšā одной no veciem un jau pamestiem rakstiem es rakstīju par to, cik vienkārši un dabiski var pārraidīt video no kanvas, izmantojot tīmekļa ligzdas. Šajā rakstā es īsi runāju par to, kā uzņemt video no kameras un skaņu no mikrofona, izmantojot MediaStream API, kā iekodēt saņemto straumi un nosūtīt to caur websocket uz serveri. Taču patiesībā viņi to nedara, apraidēm izmanto vai nu īpašu programmatūru, kas jāinstalē un jākonfigurē. Atvērt Broadcast Software, vai arī viņi izmanto WebRTC, kas darbojas uzreiz no kastes, proti, nav jāinstalē nekādi spraudņi a la flash player, kas tiks izgriezts no Chromium pārlūka jau decembrī.

Šodien mēs runāsim par WebRTC.

Tīmekļa reāllaika saziņa (WebRTC) nav viens protokols, tā ir vesela standartu, protokolu un JavaScript API kolekcija, kas kopā nodrošina vienādranga reāllaika video-audio saziņu, kā arī var izmantot, lai pārsūtītu jebkuru binārie dati. Parasti pārlūkprogrammas darbojas kā vienaudži, taču tā var būt arī, piemēram, mobilā lietojumprogramma. Lai organizētu p2p komunikāciju starp klientiem, ir nepieciešams pārlūkprogrammas atbalsts dažāda veida video un audio kodēšanai, atbalsts dažādiem tīkla protokoliem, nodrošinot aparatūras mijiedarbību ar pārlūkprogrammu (caur OS slāņiem): tīmekļa kameras, skaņas kartes. Izstrādātāja ērtībām visa šī tehnoloģiju virkne ir paslēpta aiz JavaScript API abstrakcijas.

Tas viss sastāv no trim API:

  • MediaStream API — pagājušajā reizē demontēts, šodien par viņu uzrakstīšu nedaudz vairāk. Kalpo video/audio straumju saņemšanai no aparatūras

  • RTCPeerConnection — nodrošina saziņu starp diviem klientiem (p2p)

  • RTCDataChannel - kalpo patvaļīgu datu pārsūtīšanai starp diviem klientiem

Audio un video straumju sagatavošana pārraidei

Viss sākas ar tīmekļa kameras un mikrofona multivides straumju "uztveršanu". Protams, neapstrādātas straumes nav piemērotas telekonferences organizēšanai, katra straume ir jāapstrādā: jāuzlabo kvalitāte, jāsinhronizē audio ar video, jāievieto sinhronizācijas atzīmes video straumē un jānodrošina nepārtraukti mainīgajam kanāla joslas platumam atbilstošs bitu pārraides ātrums. . Par to visu rūpējas pārlūkprogramma, izstrādātājam pat nav jāuztraucas par multivides straumju kodēšanas nodrošināšanu. Mūsdienu pārlūkprogrammā jau ir programmatūras slāņi uztveršanai, kvalitātes uzlabošanai (noņemt atbalsi un troksni no skaņas, uzlabot attēlu), video un audio kodēšanai. Slāņu shēma ir parādīta attēlā. 1:

(Gandrīz) bezjēdzīga tīmekļa kameras straumēšana no pārlūkprogrammas. 2. daļa. WebRTCRīsi. 1. Audio un video apstrādes slāņi pārlūkprogrammā

Visa apstrāde notiek tieši pašā pārlūkprogrammā, bez papildu. nav nepieciešami spraudņi. Tomēr 2020. gadā lietas joprojām nav tik rožainas. Ir pārlūkprogrammas, kuras vēl pilnībā neatbalsta MediaStream API, varat sekot saitei un redzēt saderības tabulu pašā apakšā. Īpaši IE atkal sagādā vilšanos.

Ar saņemtajām straumēm var paveikt ļoti interesantas lietas: var klonēt, mainīt video izšķirtspēju, manipulēt ar audio kvalitāti, paņemt un “pieķert” Media Stream straumi. tagu un paskaties uz sevi html lapā. Vai arī varat uzzīmēt straumi uz audekla un iestatīt WebGL vai CSS3 un lietot dažādus filtrus video, tvert apstrādāto video no kanvas un pēc tam nosūtīt to tīklā uz serveri, pārkodēt un publicēt visiem (hello bigo live, twitch un citi). Šeit es neanalizēšu, kā šādas lietas tiek darītas, es sniegšu pāris tīmeklī atrastus piemērus:

https://jeeliz.com/ - puiši veido reāllaika CV Javascript. Viņiem ir veselums arsenāls dažādas js bibliotēkas darbam ar video straumi uz audekla: seju, objektu noteikšana, filtru pielietošana (maskas, piemēram, Instagram) utt. Lielisks piemērs tam, kā jūs varat apstrādāt reāllaika video tieši pārlūkprogrammā bez papildu spraudņiem.

Canvas captureStream API - API dokumentācija video straumes uzņemšanai no audekla. Jau tiek atbalstīts pārlūkprogrammās Chrome, Opera un Firefox

RTCPeerConnection

Tātad mēs nonācām pie lietas, bet kā faktiski pārsūtīt video citam lietotājam? Iznāk priekšplānā RTCPeerConnection. Īsāk sakot, gandrīz šajā solī jums ir jāizveido RTCPeerConnection objekts:

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

Kā vienu no iespējām norādām iceServers – tas ir serveris, kas palīdz nodrošināt savienojumu starp divām pārlūkprogrammām aiz NAT'om. Tas ir, problēma šeit ir atrisināta: kā uzzināt sarunu biedra IP, ja viņš ir aiz sava pakalpojumu sniedzēja NAT? ICE protokols nāk palīgā, patiesībā ICE vispār neattiecas uz WebRTC, bet par to vēlāk.

Iepriekš mēs saņēmām Usermedia straumes:

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

Pēc tam notikums onnegotiationneeded tiek aktivizēts peerConnection, kura apdarinātājā mums ir jāizveido piedāvājums (SDP izteiksmē — Session Description Protocol) un jāpiešķir tas peerConnection, izmantojot metodi setLocalDescription. Par SDP - kas tas ir un par piedāvājumu un atbilžu formātiem - runāsim tālāk.

Pēc LocalDescription peerConnection piešķiršanas pārlūkprogramma "samontē" ledus kandidātus, tas ir, atrod dažādus veidus, kā sazināties, izmantojot NAT. Notikums “onicegatheringstatechange” aizdegas. Onicegatheringstatechange apdarinātājā mēs pieļaujam savienojumu ar webrtc-signaling-server straumi, lai apmainītos ar sesijas aprakstu starp vienaudžiem:

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 ir serveris, kas nepieciešams, lai apmainītos ar sesijas aprakstu starp diviem vienaudžiem, tas var būt vienkāršākais tīmekļa ligzda vai xhr-serveris jebkurā PL. Tās uzdevums ir vienkāršs: pieņemt sesijas aprakstu no viena līdzinieka un pārsūtīt to citam.

Pēc sesiju aprakstu apmaiņas abas puses ir gatavas pārraidīt un saņemt video straumes, tajā pusē, kas uztver video straumi, uz peerConnection tiek iedarbināts ontrack notikums, kura apdarinātājā saņemtos ierakstus var piešķirt un paskaties uz savu mīļāko sarunu biedru. Papildu teorija un detaļas.

Saites un literatūra:

https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection - dokumentācija RTCPeerConnection

https://github.com/pion/webrtc - WebRTC protokolu ieviešana ceļā

https://webrtcforthecurious.com/ - grāmata no pion radītājiem

https://hpbn.co/ - Rezervējiet augstas veiktspējas pārlūkprogrammas tīklu. Detalizēti tiek apspriesti jautājumi par tīmekļa lietojumprogrammu augstas veiktspējas nodrošināšanu. Beigās ir aprakstīts WebRTC. Grāmata noteikti ir veca (2013), taču nezaudē savu aktualitāti.

Nākamajā daļā es vēlos sniegt nedaudz vairāk teorijas un praksē analizēt video straumes uztveršanu un apstrādi serverī, izmantojot pion, pārkodējot uz HLS, izmantojot ffmpeg, lai pēc tam pārraidītu skatītājiem pārlūkprogrammā.

Nepacietīgajiem: mans ļoti neapstrādātais prototips video pārraidīšanai no tīmekļa kameras, lai reaģētu caur pionu serveri. (tas ir tikai eksperiments).

Avots: www.habr.com

Pievieno komentāru