Engang i , hvordan man kan kode den modtagne strøm og sende den gennem websockets til serveren. Men i virkeligheden gør man ikke sådan; til streaming bruger man enten særlig software, som man skal installere og konfigurere: en hurtig eksempel kunne være Open Broadcast Software I dag taler vi om WebRTC.
Web Real-Time Communication (WebRTC) er ikke bare et protokol, det er en hel samling af standarder, protokoller og JavaScript API'er, der samlet set muliggør peer-to-peer video-lyd kommunikation i realtid og kan bruges til overførsel af enhver binær data. Normalt fungerer browsere som peering-enheder, men det kan også være en mobilapplikation, for eksempel. For at organisere p2p kommunikation mellem klienter kræves det, at browseren understøtter forskellige typer video- og lydkodning, understøttelse af mange netværksprotokoller samt sikring af interaktion mellem hardware og browser (gennem OS-lag): webcams, lydkort. Hele denne blanding af teknologier er skjult bag en abstraktion af JavaScript API for udviklerens bekvemmelighed.
Det hele ender i sidste ende med tre API'er:
— som vi dækkede sidste gang, i dag vil jeg skrive lidt mere om det. Det bruges til at modtage video/lyd streams fra 'hardwaren'
RTCPeerConnection
— bruges til at overføre vilkårlige data mellem to klienter
Forberedelse af lyd- og videostreams til overførsel
Подготовка аудио и видео потоков к передаче
Det hele starter med "fangsten" af medie-strømme fra webcam og mikrofon. Rå strømme er naturligvis ikke egnede til at organisere telekonferencer, hver strøm skal behandles: forbedre kvaliteten, synkronisere lyd med video, placere synkroniseringsmærker i videostrømmen, og sikre en passende bitrate, der konstant tilpasser sig kanalens båndbredde. Browseren håndterer alt dette, udviklere behøver ikke bekymre sig om at sikre kodning af mediestrømme. Inden i en moderne browser findes der allerede softwarelag til optagelse, kvalitetsforbedring (fjerne ekko og støj fra lyden, forbedre billedet), samt kodning af video og lyd. Lag-diagrammet er vist i fig. 1:
Fig. 1. Lag af audio og video behandling i browseren
Al behandling foregår direkte i selve browseren, ingen yderligere plugins er nødvendige. Men det er stadig ikke så rosenrødt i 2020. Der er stadig browsere, som ikke helt understøtter , du kan klikke på linket og se kompatibilitetstabellen helt nederst. Især skuffer IE igen.
Med de indhentede strømme kan man lave meget interessante ting: man kan klone, ændre videaufløsningen, manipulere lydkvaliteten, man kan "hæfte" en Media Stream strøm til
— folk arbejder med realtime CV på Javascript. De har en hel af forskellige js-biblioteker til at arbejde med videostrømmen på canvas: ansigts- og objektgenkendelse, påføring af filtre (masker, som på Instagram) osv. Et fremragende eksempel på, hvordan man kan behandle video i realtid direkte i browseren uden yderligere plugins.
— API-dokumentation til optagelse af videostrøm fra canvas. Allerede understøttet i Chrome, Opera og Firefox.
— muliggør kommunikation mellem to klienter (p2p)
Nu er vi nået frem til, hvordan man egentlig sender video til en anden bruger? Det første skridt er For a brief overview, at this stage, you need to create a RTCPeerConnection object:
const peerConnection = new RTCPeerConnection({
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
});One of the options is to specify iceServers — this is a server that helps establish a connection between two browsers behind a NAT. This addresses the issue of how to find out the IP of the dialog partner if they are behind their provider's NAT. The ICE protocol comes to the rescue; in fact, ICE is not directly related to WebRTC, but more on that later.
Previously, we obtained Usermedia streams:
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
// Usermedia streams, usually this is video and audio
const tracks = stream.getTracks();
for (const track of tracks) {
// each track is added to peerConnection
peerConnection.addTrack(track);
}
}).catch(console.error);Next, the onnegotiationneeded event is triggered on peerConnection, where we need to create an offer (in terms of SDP — Session Description Protocol) and set it in peerConnection using the setLocalDescription method. We'll discuss what SDP is and the formats of offer and answer later.
After assigning LocalDescription to peerConnection, the browser 'gathers' ICE candidates, which means it finds different paths for communication through NAT. The onicegatheringstatechange event is triggered. In the onicegatheringstatechange handler, we allow the connection with the webrtc-signaling server stream to exchange Session Description between peers:
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);
}
};The webrtc-signaling server is required to facilitate the exchange of session descriptions between two peers. This can be a simple websocket or XHR server in any programming language. Its task is straightforward: to receive a session description from one peer and relay it to the other.
After exchanging Session descriptions, both parties are ready to transmit and receive video streams. On the receiving side, when receiving the video stream, the ontrack event is triggered on peerConnection, and in its handler, the received tracks can be assigned to
References and literature:
— documentation
— implementation of WebRTC protocols in Go
— booklet from the creators of Pion
— the book High Performance Browser Networking. It delves into issues of ensuring high performance in web applications. At the end, it discusses WebRTC. The book is somewhat dated (2013), but still relevant.
I den næste del vil jeg gerne give lidt mere teori og praktisk opdeling af metoden til håndtering af videostrømmen på serveren ved hjælp af pion, transkodning til HLS via ffmpeg til efterfølgende transmission til seerne i browseren.
For de utålmodige: (det er bare et eksperiment).
Kilde: habr.com
