Un jour dans l'un des anciens articles oubliés, j'ai parlé de la facilité avec laquelle on peut diffuser des vidéos à partir d'un canvas via des websockets. Dans cet article, j'ai brièvement expliqué comment capturer la vidéo d'une caméra et le son d'un microphone à l'aide de , comment encoder le flux obtenu et l'envoyer via des websockets au serveur. Cependant, en réalité, on ne fait pas cela; pour les diffusions, on utilise soit un logiciel spécifique qui nécessite une installation et une configuration, comme par exemple , soit on utilise WebRTC, qui fonctionne directement sans nécessiter l'installation de plugins comme Flash Player, qui sera retiré de Chromium en décembre.
Aujourd'hui, nous allons parler de WebRTC.
Web Real-Time Communication (WebRTC) n'est pas un simple protocole, mais une collection entière de normes, de protocoles et d'API JavaScript qui ensemble permettent des communications vidéo et audio en temps réel entre pairs, et peuvent également être utilisés pour transmettre des données binaires. En général, les pairs sont des navigateurs, mais cela peut aussi être une application mobile, par exemple. Pour organiser une communication p2p entre les clients, le navigateur doit prendre en charge divers types de codage vidéo et audio, prendre en charge de nombreux protocoles réseau, et assurer l'interaction du matériel avec le navigateur (via les couches du système d'exploitation) : webcams, cartes audio. Tout ce mélange technologique est caché derrière l'abstraction de l'API JavaScript pour le confort des développeurs.
Tout se résume finalement à trois API :
— que nous avons exploré la dernière fois, aujourd'hui j'écrirai un peu plus à son sujet. Il sert à obtenir des flux vidéo/audio de 'matériel'
— fournit des communications entre deux clients (p2p)
— sert à transmettre des données arbitraires entre deux clients
Préparation des flux audio et vidéo pour la transmission
Tout commence par la « capture » des flux médias de la webcam et du micro. Les flux bruts ne conviennent bien sûr pas à l'organisation d'une téléconférence. Chaque flux doit être traité : améliorer la qualité, synchroniser l'audio avec la vidéo, établir des marques de synchronisation dans le flux vidéo, et garantir un bitrate correspondant à la largeur de bande constamment changeante. Le navigateur s'occupe de tout cela, le développeur n'a même pas à se soucier de l'encodage des flux médias. À l'intérieur d'un navigateur moderne, il existe déjà des couches logicielles de capture, d'amélioration de la qualité (supprimer l'écho et le bruit du son, améliorer l'image), et d'encodage vidéo et audio. Le schéma des couches est illustré à la figure 1 :
Fig. 1. Couches de traitement audio et vidéo dans le navigateur
Tout le traitement a lieu directement dans le navigateur, sans plugins supplémentaires nécessaires. Cependant, la situation n'est pas encore aussi rose en 2020. Il reste des navigateurs qui ne prennent pas encore complètement en charge , vous pouvez suivre le lien et consulter le tableau de compatibilité tout en bas. En particulier, IE déçoit encore une fois.
Avec les flux obtenus, il est possible de faire des choses très intéressantes : cloner, modifier la résolution vidéo, manipuler la qualité audio, on peut prendre et “attacher” un flux Media Stream à une balise <video> et se regarder dans la page html. On peut aussi dessiner le flux sur un canvas, y appliquer WebGL ou CSS3, et superposer divers filtres sur la vidéo, capturer la vidéo traitée depuis le canvas et ensuite l'envoyer sur le réseau au serveur pour la transcoder et la publier à tous ceux qui le souhaitent (salut bigo live, twitch et autres). Ici, je ne vais pas expliquer comment tout cela se fait, je vais donner quelques exemples trouvés sur le net :
— des gars travaillent sur la CV en temps réel sur Javascript. Ils ont tout un de diverses bibliothèques js pour travailler avec le flux vidéo sur canvas : détection de visages, objets, superposition de filtres (masques, comme sur Instagram) et autres. Un excellent exemple de la façon dont on peut traiter la vidéo en temps réel directement dans le navigateur sans plugins supplémentaires.
— documentation API sur la capture des flux vidéo à partir du canvas. Déjà pris en charge dans Chrome, Opera et Firefox.
RTCPeerConnection
Nous en arrivons donc à la question de la manière de transmettre la vidéo à un autre utilisateur ? En résumé, à cette étape, vous devez créer un objet RTCPeerConnection :
const peerConnection = new RTCPeerConnection({
iceServers: [{
urls: 'stun:stun.l.google.com:19302'
}]
});L'une des options que nous spécifions est iceServers — un serveur qui aide à établir une connexion entre deux navigateurs derrière un NAT. Cela signifie que nous résolvons le problème : comment connaître l'IP d'un interlocuteur s'il est derrière le NAT de son fournisseur ? Le protocole ICE vient à la rescousse, en réalité, ICE n'est pas directement lié à WebRTC, mais nous en parlerons plus tard.
Auparavant, nous avons obtenu des flux Usermedia :
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
// Flux Usermedia, généralement vidéo et audio
const tracks = stream.getTracks();
for (const track of tracks) {
// chaque piste est ajoutée à peerConnection
peerConnection.addTrack(track);
}
}).catch(console.error);Ensuite, sur le peerConnection, l'événement onnegotiationneeded se déclenche, dans son gestionnaire, nous devons créer une offre (en termes de SDP — Session Description Protocol) et l'assigner au peerConnection via la méthode setLocalDescription. Nous discuterons du SDP — ce que c'est et des formats offre et réponse — plus tard.
Après l'assignation de la LocalDescription au peerConnection, le navigateur "assemble" les candidats ICE, c'est-à-dire qu'il trouve différents chemins pour établir la communication à travers le NAT. L'événement onicegatheringstatechange se déclenche. Dans le gestionnaire onicegatheringstatechange, nous autorisons la connexion avec le serveur de signalisation webrtc pour échanger des descriptions de session entre les pairs :
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);
}
};Le serveur de signalisation webrtc — est un serveur nécessaire pour assurer l'échange de descriptions de session entre deux pairs, cela peut être un simple serveur websocket ou xhr sur n'importe quel langage de programmation. Sa tâche est simple : recevoir la description de session d'un pair et la transmettre à l'autre.
Après l'échange des descriptions de session, les deux parties sont prêtes à diffuser et à recevoir des flux vidéo, du côté qui reçoit le flux vidéo, l'événement ontrack se déclenche sur le peerConnection, dans son gestionnaire, les pistes reçues peuvent être assignées au
Liens et littérature :
— documentation
— mise en œuvre des protocoles WebRTC en go
— petit livre des créateurs de pion
— livre High Performance Browser Networking. Il aborde en détail les questions d'optimisation des performances des applications web. À la fin, il traite de WebRTC. Le livre est certes ancien (2013), mais reste d'actualité.
Dans la partie suivante, je souhaite donner un peu plus de théorie et examiner en pratique la capture et le traitement du flux vidéo sur le serveur avec pion, la transcodification en HLS via ffmpeg pour la diffusion ultérieure aux spectateurs dans leur navigateur.
Pour les impatients : (c'est juste une expérience).
Source : habr.com
