Dikur në nga artikujt e vjetër dhe tashmë të braktisur, kam shkruar se si mund të transmetohet lehtësisht dhe pa stres video nga canvas përmes websockets. Në atë artikull përmenda si të kapësh videon nga kamera dhe zërin nga mikrofonin përmes , si të kodosh dhe dërgosh rrjedhën e prodhuar përmes websockets në server. Megjithatë, në realitet nuk bëhet kështu, për transmetime përdoret ose software i veçantë që duhet të instalohet dhe konfigurohet: për të thënë një gjë, mund të jetë , ose aktivizojnë WebRTC, i cili funksionon direkt nga kutia, domethënë nuk kërkon instalimin e ndonjë plugin-i si flash player, i cili do të hiqet nga Chromium browseri në dhjetor.
Sot do të flasim për WebRTC.
Web Real-Time Communication (WebRTC) nuk është një protokoll i vetëm, është një koleksion i standardeve, protokolleve dhe API JavaScript, të cilat së bashku sigurojnë komunikim audio-video në kohë reale peer-to-peer, si dhe mund të përdoren për të transmetuar çdo të dhëna binare. Në përgjithësi, pikat e lidhjes janë shfletuesit, por mund të jetë edhe një aplikacion mobil, për shembull. Për të organizuar komunikimin p2p midis klientëve, kërkohet mbështetje nga shfletuesi për lloje të ndryshme të kodimit të videos dhe audios, mbështetje për një sërë protokollesh rrjetesh, dhe sigurimi i ndërveprimit të harduerit me shfletuesin (përmes shtresave të OS): kamera, kartela zanore. E gjithë kjo përzierje teknologjish fshihet pas abstraksionit të API JavaScript për lehtësinë e zhvilluesit.
Në fund, gjithçka përfundon në tre API:
— e diskutuar herën e kaluar, sot do të shkruaj edhe pak mbi të. Shërben për të marrë rrjedhat video/audio nga «hardueri»
— siguron komunikime midis dy klientëve (p2p)
— shërben për të transmetuar të dhëna të rastësishme midis dy klientëve
Përgatitja e rrjedhave audio dhe video për dërgesë
Çdo gjë fillon me "kapjen" e mediave nga kamera dhe mikrofonët. Përshtatjet e papërpunuara sigurisht që nuk janë të dobishme për organizimin e telekonferencave; çdo rrjedh mediash duhet të përpunojë: të përmirësojë cilësinë, të sinkronizojë audio me video, të vendosë pika sinkronizimi në rrjedhën video, të sigurojë një bitrate të përshtatshëm që ndryshon vazhdimisht me gjerësinë e kanalit. Shfletuesi merr përsipër gjithçka, zhvilluesi as nuk ka nevojë të shqetësohet për kodimin e mediave. Brenda një shfletuesi modern, tashmë ekzistojnë shtresa programore për kapjen, përmirësimin e cilësisë (heqjen e jehonës dhe zhurmave nga tingulli, përmirësimin e imazhit), kodimin e videove dhe audios. Skema e shtresave është e paraqitur në fig. 1:
Fig. 1. Shtresat e përpunimit të audio dhe videos në shfletues
E tëra përpunimi ndodh direkt në shfletues, nuk kërkohen pluga shtesë. Megjithatë, situata nuk është kaq optimiste në vitin 2020. Ka ende shfletues që nuk e përkrahin plotësisht , mund të kaloni në lidhje dhe në fund të faqes të shihni tabelën e përputhshmërisë. Sidomos IE përsëri zhgënjen.
Me rrjedhët e marra mund të bëni gjëra shumë interesante: mund të klononi, të ndryshoni përmasat e videos, të manipulojnë cilësinë e audios, mund të merrni dhe "të lidhni" rrjedhën Media Stream me tagun <video> dhe ta shikoni veten në faqen html. Po ashtu mund të vizatoni rrjedhën në canvas, ta drejtoni me WebGL ose CSS3 dhe të aplikoni filtra të ndryshëm mbi video, të kapni videon e përpunuar nga canvas dhe më pas ta dërgoni në rrjet në server, ta transcodnoj dhe ta publikoni për të gjithë ata që duan (përshendetje bigo live, twitch dhe të tjerët). Këtu nuk do të analizoj se si bëhen këto gjëra; do të sjell disa shembuj, të gjetura në hapësirat e internetit:
— djemtë merren me CV në kohë reale me Javascript. Ata kanë një të biblioteqave të ndryshme js për të punuar me rrjedhën video në canvas: identifikimi i fytyrave, objekteve, aplikimi i filtrave (maskave, si në Instagram) etj. Një shembull i shkëlqyer se si pa pluga shtesë mund të përpunosh video në kohë reale direkt në shfletues.
— dokumentacioni i API për kapjen e rrjedhës video nga canvas. Tashmë mbështetet në Chrome, Opera dhe Firefox.
RTCPeerConnection
Këtu kemi arritur në pikën se si të dërgojmë videon te një përdorues tjetër? Në plan të parë del . Nëse flasim shkurt, 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 që specifikojmë është iceServers — ky është një server që ndihmon në sigurimin e lidhjes mes dy shfletuesve që ndodhen pas NAT. Kështu, këtu zgjidhet problemi: si ta gjejmë IP-në e biseduesit nëse ai ndodhet pas NAT-it të ofruesit të tij? Në ndihmë vjen protokolli ICE, i cili, në të vërtetë, nuk i përket WebRTC, por për këtë më vonë.
Më parë morëm rrjedhat e Usermedia:
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
// Rrjedhat e Usermedia, zakonisht janë video dhe audio
const tracks = stream.getTracks();
for (const track of tracks) {
// çdo track e bashkëngjisim në peerConnection
peerConnection.addTrack(track);
}
}).catch(console.error);Më pas, në peerConnection ndodh ngjarja onnegotiationneeded, në trajtuesin e së cilës ne duhet të krijojmë një ofertë (në terma të SDP — Protokolli i Përshkrimit të Sesionit) dhe ta caktojmë në peerConnection përmes metodës setLocalDescription. Rreth SDP — çfarë është dhe mbi formatet ofertë dhe përgjigje — do flasim më vonë.
Pas caktimit të LocalDescription të peerConnection, shfletuesi "mbledh" kandidatët ice, pra gjen rrugë të ndryshme për komunikim përmes NAT-it. Aktivizohet ngjarja onicegatheringstatechange. Në trajtuesin onicegatheringstatechange lejojmë lidhjen me serverin webrtc-signaling për shkëmbimin e Përshkrimit të Sesionit mes pirave:
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 pirave, mund të jetë një websocket ose server xhr në çdo gjuhë programuese. Detyra e tij është e thjeshtë: të pranojë përshkrimin e sesionit nga një pirë dhe t'ia dërgojë tjetrës.
Pas shkëmbimit të përshkrimeve të sesionit, të dy palët janë gati për të transmetuar dhe pranuar rrjedha video, nga ana që pranon rrjedhën video aktivizohet ngjarja ontrack në peerConnection, në trajtuesin e së cilës, rrjedhat e marra mund të caktohen në
Lidhjet dhe literatura:
— dokumentacioni
— implementimi i protokolleve WebRTC në go
— një libër nga krijuesit e pion
— libri High Performance Browser Networking. Në detaje diskutojnë çështjet e sigurimit të performancës së lartë të aplikacioneve web. Në fund përshkruhet WebRTC. Libri është sigurisht i vjetër (2013), megjithatë mbetet i rëndësishëm.
Në këtë pjesë tjetër, dëshiroj të ofroj pak teori dhe për të shqyrtuar praktikisht pranimin dhe përpunimin e videokanalit në server me ndihmën e pion, transkodimin në HLS përmes ffmpeg për transmetim të mëtejshëm te shikuesit në shfletues.
Për ata që janë të padurueshëm: (kjo është thjesht një eksperiment).
Burimi: habr.com
