Kordagi vana ja juba mahajäetud artiklis kirjutasin, kui lihtne ja loomulik on edastada videot canvas'ilt websockets kaudu. Selles artiklis rääkisin pinnapealselt, kuidas jäädvustada videot kaamerast ja heli mikrofonist kaudu , kuidas saadud voogu kodeerida ja saata websockets abil serverisse. Kuid reaalsuses nii ei tehta, edastamiseks kasutatakse kas spetsiaalset tarkvara, mille peab paigaldama ja seadistama: näiteks võib öelda, et see on , või kasutatakse WebRTC-d, mis töötab otse välja
Täna räägime WebRTC-st.
Web Real-Time Communication (WebRTC) ei ole ainult üks protokoll, vaid terve kogum standardeid, protokolle ja JavaScript API-sid, mis kõik koos tagavad peer-to-peer video- ja helikommunikatsiooni reaalajas ning võivad olla kasutatud ka mis tahes binaarsete andmete edastamiseks. Tüüpilised peer'id on brauserid, kuid see võib olla ka mobiilirakendus, näiteks. Selleks, et korraldada p2p suhtlemist klientide vahel, on brauseri toetamine erinevatele video- ja helikodeeringutele, mitmesuguste võrguprotokollide tugi ning riistvara ja brauseri (operatsioonisüsteemi kihtide kaudu) koosoleku tagamine vajalik: veebikaamerad, helikaardid. Kõik see tehnoloogiate segu on JavaScript API abstraktsiooni taga, et katteta arendaja mugavuse huvides.
Lõppkokkuvõttes koondub see kolme API juurde:
— arutasime eelmine kord, täna kirjutan sellest veel natuke. See teenib video/heli voogude saamiseks "riistvarast"
— tagab suhtluse kahe kliendi vahel (p2p)
— teenib kahe kliendi vahel igasuguste andmete edastamiseks
Audio ja video voogude ettevalmistamine edastamiseks
Kõik algab veebikaamerate ja mikrofoni meediavoogude "kinni püüdmisest". Toorvood ei sobi igal juhul telekonverentsi korraldamiseks; iga voog tuleb töödelda: parandada kvaliteeti, sünkroniseerida heli ja video, paigutada sünkroontäpid videovoogu ning tagada, et bitikiirus vastaks pidevalt muutuvale kanalilaiusele. Selle kõigega tegeleb brauser, arendajal ei ole isegi vajalik muretseda meediavoogude kodeerimise pärast. Kaasaegses brauseris on juba olemas programmikihtide süsteem, mis tegeleb salvestamise, kvaliteedi parandamise (kõrvaldades kaja ja müra, parandades pildi) ja video ning audio kodeerimisega. Kihikava on näidatud joonisel 1:
Joonis 1. Audio ja video töötlemise kihid brauseris
Kogu töötlemine toimub otse brauseris, lisalisandite kasutamine ei ole vajalik. Siiski pole olukord 2020. aastal nii roosiline. On jäänud brausereid, mis ei toeta seda täielikult , saate minna lingile ja vaadata tabelit ühilduvuse kohta. Eriti pettumust valmistab IE taas.
Saadud voogudega saab teha väga huvitavaid asju: näiteks saab kloonida, muuta video eraldusvõimet, manipuleerida audio kvaliteediga, saab "üles riputada" Media Stream voog <video> sildile ja vaadata enda lemmikuvastust HTML lehel. Võite ka voogu joonistada canvas'ile, suunata WebGL-i või CSS3-iga ning rakendada erinevaid filtreid video peale, salvestada töödeldud video canvas'ilt ja seejärel edastada võrgu kaudu serverisse, transkodeerimiseks ja avaldamiseks kõigile soovijatele (tere bigo live, twitch ja teised). Siin ma ei hakka neid asju lahti harutama, toon välja paar näidet, mis ma internetist leidsin:
— poisid tegelevad reaalajas CV-ga Javascriptis. Neil on terve erinevaid js-raamatukogusid videovoogude töötlemiseks canvas'el: näotuvastus, objektide jälgimine, filtrite (maskide, nagu Instagramis) lisamine jne. Suurepärane näide sellest, kuidas ilma lisalisanditeta saab brauseris reaalajas videot töödelda.
— dokumentatsioon canvas'ilt videovoogude tabamise API jaoks. Toetatakse juba Chrome'is, Operas ja Firefoxis
RTCPeerConnection
Nüüd oleme ikkagi jõudnud küsimuseni, kuidas video teisele kasutajale edastada? Esiplaanile tõuseb Lühidalt öeldes peate sellel etapil looma RTCPeerConnection objekti:
const peerConnection = new RTCPeerConnection({
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
});Ühe võimalusena määrame iceServers — see on server, mis aitab tagada ühenduse kahe brauseri vahel, mis asuvad NAT'i taga. See tähendab, et siin lahendame probleemi: kuidas teada saada vastaspoole IP-d, kui ta on tema teenusepakkuja NAT-i taga? Siin tuleb appi ICE protokoll, tegelikult ei kuulu ICE üldse WebRTC alla, aga sellest hiljem.
Varem saime Usermedia voogusid:
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
// Usermedia vood, tavaliselt video ja audio
const tracks = stream.getTracks();
for (const track of tracks) {
// iga rada ühendatakse peerConnection'iga
peerConnection.addTrack(track);
}
}).catch(console.error);Järgmisel sammul toimub peerConnection'is sündmus onnegotiationneeded, mille käsitlemisel peame looma offer'i (SDP — Session Description Protocol'i terminoloogias) ja määrama selle peerConnection'is meetodi setLocalDescription abil. SDP kohta — mis see on ja offers ja answers formaadist — räägime hiljem.
Pärast LocalDescription'i määramist peerConnection'ile, kogub brauser ice-kandidaate, see tähendab, et ta otsib erinevaid teid kommunikatsiooniks läbi NAT'i. Toimub sündmus onicegatheringstatechange. Käsitlemisel on icegatheringstatechange me peame lubama ühenduse webrtc-signaling-serveriga, et vahetada Session Description'id piramide vahel:
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 — see on server, mis on vajalik session description'i vahetamiseks kahe pirami vahel, see võib olla kõige lihtsam websocket või xhr-server igas programmeerimiskeeles. Tema ülesanne on lihtne: võtta session description ühe pira käest ja edastada teisele.
Pärast Session description'ide vahetamist on kummalgi poolel valmis video voogude edastamiseks ja vastuvõtmiseks, poolel, mis video voogu vastu võtab, toimub peerConnection'is sündmus ontrack, mille käsitlemisel saame saadud rajad määrata
Lingid ja kirjandus:
— dokumentatsioon
— WebRTC protokollide teostamine Go's
— raamat väikestelt pion-tüüpi loojatelt
— raamat High Performance Browser Networking. Üksikasjalikult käsitletakse web-rakenduste kõrge jõudluse tagamise küsimusi. Raamatu lõpus käsitletakse WebRTC-d. Raamat on muidugi vana (2013), kuid ei kaota oma olulisust.
järgmisel osal tahan anda veel natuke teooriat ja praktiliselt arutada videovoogu serveris töötlemise meetodit pion'i abil, HLS'i kaudu ffmpeg'iga transkodeerimise tegemine, et edastada seda vaatajatele brauseris.
Pingealistele: (see on lihtsalt eksperiment).
Allikas: habr.com
