Le premier problème de visionneuse ou les difficultés de conversion des flux vidéo WebRTC en HLS


George ferma son ordinateur portable et se frotta les yeux rouges privés de sommeil. "Les clients continuent de se plaindre du gel des flux; le nouveau package de correctifs n'a pas aidé du tout! Que dois-je faire avec ce HLS (censuré)?" dit-il.


Le navigateur n'est pas seulement hypertexte, mais aussi un streamer


Les navigateurs ont des joueurs depuis longtemps, mais l'histoire est différente avec l'encodeur vidéo et le streaming. Désormais, dans presque tous les navigateurs de la dernière version, nous pouvons trouver des modules d'encodage, de streaming, de décodage et de lecture. Ces fonctions sont disponibles via l'API JavaScript et l'implémentation est appelée Web Real Time Communications ou WebRTC. Cette bibliothèque intégrée aux navigateurs peut faire beaucoup: capturer de la vidéo à partir d'une caméra intégrée, virtuelle ou USB, la compresser avec les codecs H.264, VP8 et VP9 et l'envoyer au réseau via le protocole SRTP; c'est-à-dire qu'il fonctionne comme un encodeur vidéo de streamer logiciel. En conséquence, nous voyons un navigateur qui a quelque chose de similaire à ffmpeg ou gstreamer, compresse bien la vidéo, diffuse sur RTP et lit les flux vidéo.


WebRTC nous donne la liberté d'implémenter une variété de cas de streaming en JavaScript:


  • diffuser depuis le navigateur vers le serveur pour l'enregistrement et la distribution ultérieure
  • distribuer des flux d'égal à égal
  • lire le flux d'un autre utilisateur et envoyer le sien (chat vidéo)
  • convertir d'autres protocoles par le serveur, par exemple RTMP, RTSP, etc., et les lire dans le navigateur en tant que WebRTC

Les scripts de contrôle de flux raffinés peuvent ressembler à ceci:


//Launching broadcast from browser to server session.createStream({name:”mystream”}).publish(); //Playing broadcast by the browser session.createStream({name:”mystream”}).play(); 

HLS fonctionne là où WebRTC ne fonctionne pas


WebRTC fonctionne dans les dernières versions des navigateurs, cependant, il y a les deux facteurs suivants: 1) Tous les utilisateurs ne mettent pas à jour leurs navigateurs en temps opportun et peuvent bien utiliser l'ancienne version de Chrome pendant trois ans. 2) Des mises à jour et de nouveaux navigateurs, WebView, ainsi que d'autres clients et messageries instantanées aidant les utilisateurs à surfer sur Internet sont publiés presque une fois par semaine. Inutile de dire que tous ne prennent pas en charge WebRTC, et s'ils le font, cela peut être limité. Voyez comment les choses vont maintenant:



Les appareils préférés de tout le monde par Apple peuvent être un casse-tête. Ils n'ont commencé à prendre en charge WebRTC que récemment et parfois, leur comportement par rapport aux navigateurs Webkit peut sembler surprenant. Lorsque WebRTC ne fonctionne pas ou ne fonctionne pas très bien, HLS fonctionne correctement. À cet égard, la compatibilité est requise, et quelque chose comme un convertisseur qui nous permet de convertir WebRTC en HLS et de le lire sur presque tous les appareils.


HLS n'a pas été initialement conçu pour les flux en temps réel. En effet, comment diffuser des vidéos en temps réel via HTTP? La tâche de HLS est de couper la vidéo en morceaux et de la livrer au joueur en douceur, sans précipitation, en les téléchargeant une par une. Un lecteur HLS attend un flux vidéo strictement formé et fluide. Ici, nous avons un conflit, car WebRTC, au contraire, peut se permettre de perdre des paquets en raison d'exigences en temps réel et d'une faible latence et a un FPS / GOP flottant et un débit binaire variable - être l'exact opposé de HLS en termes de prévisibilité et la régularité du flux.


Une approche évidente - la dépackétisation WebRTC (SRTP) et la conversion ultérieure en HLS peuvent ne pas fonctionner dans un lecteur Apple HLS natif ou fonctionner avec le gel, qui est une forme impropre à la production. Le lecteur natif désigne un lecteur utilisé dans Apple iOS Safari, Mac OS Safari et Apple TV.


Par conséquent, si vous remarquez le gel HLS dans le lecteur natif, c'est peut-être le cas, et la source du flux est WebRTC ou un autre flux dynamique avec un balisage inégal. De plus, dans la mise en œuvre des joueurs natifs d'Apple, il existe des comportements qui ne peuvent être compris que de manière empirique. Par exemple, le serveur doit commencer à envoyer des segments HLS immédiatement après le retour de la liste de lecture m3u8. Un délai d'une seconde peut entraîner un gel. Si la configuration du flux binaire a changé au cours du processus (ce qui est assez courant lors de la diffusion WebRTC), il y aura également un gel.


Lutter contre le gel chez les joueurs natifs


Ainsi, la dépackétisation WebRTC et la mise en paquets HLS ne fonctionnent généralement pas. Dans le serveur vidéo en streaming Web Call Server (WCS) , nous résolvons le problème de deux manières, et nous proposons la troisième alternative:


1) Transcodage.


C'est le moyen le plus fiable d'aligner un flux WebRTC sur les exigences HLS, de définir le GOP, le FPS, etc. souhaités. Cependant, dans certains cas, le transcodage n'est pas une bonne solution; par exemple, transcoder des flux 4k
de la vidéo VR est en effet une mauvaise idée. Ces flux lourds sont très coûteux à transcoder en termes de temps CPU ou de ressources GPU.



2) Adapter et aligner le flux WebRTC en déplacement pour répondre aux exigences HLS.


Ce sont des analyseurs spéciaux qui analysent le flux binaire H.264 et l'adaptent pour correspondre aux fonctionnalités / bogues des lecteurs HLS natifs d'Apple. Certes, les lecteurs non natifs comme video.js et hls.js sont plus tolérants aux flux
avec un débit binaire dynamique et FPS s'exécutant sur WebRTC et ne ralentit pas lorsque l'implémentation de référence d'Apple HLS se traduit essentiellement par un gel.



3) Utilisation de RTMP comme source de flux au lieu de WebRTC.


Malgré le fait que Flash Player est déjà obsolète, le protocole RTMP est activement utilisé pour le streaming; prenez OBS Studio, par exemple. Nous devons reconnaître que les encodeurs RTMP produisent généralement plus même
flux que WebRTC et ne provoquent donc pratiquement pas de gel dans HLS, c'est-à-dire que la conversion RTMP> HLS semble beaucoup plus appropriée en termes de gel, y compris dans les lecteurs HLS natifs. Par conséquent, si le streaming est
fait en utilisant le bureau et OBS, alors il est préférable de l'utiliser pour la conversion en HLS. Si la source est le navigateur Chrome, alors RTMP ne peut pas être utilisé sans installer de plugins, et seul WebRTC fonctionne dans ce cas.



Les trois méthodes décrites ci-dessus ont été testées et fonctionnent, vous pouvez donc choisir en fonction de la tâche.


WebRTC à HLS sur CDN


Il y a des indésirables que vous allez rencontrer dans un système distribué lorsqu'il y a plusieurs serveurs de distribution de flux WebRTC entre la source de flux WebRTC et le lecteur HLS, à savoir CDN , dans notre cas, basé sur un serveur WCS. Cela ressemble à ceci: il y a Origin - un serveur qui accepte le flux WebRTC, et il y a Edge - des serveurs qui distribuent ce flux, y compris via HLS. Il peut y avoir de nombreux serveurs, ce qui permet une mise à l'échelle horizontale du système. Par exemple, 1000 serveurs HLS peuvent être connectés à un serveur Origin; dans ce cas, la capacité du système évolue 1000 fois.



Le problème a déjà été mis en évidence ci-dessus; il survient généralement dans les lecteurs natifs: iOS Safari, Mac OS Safari et Apple TV. Par natif, nous entendons un lecteur qui fonctionne avec une indication directe de l'URL de la playlist dans
la balise, par exemple <video src="https://host/test.m3u8"/> . Dès que le joueur a demandé une playlist - et cette action est en fait la première étape de la lecture du flux HLS - le serveur doit immédiatement, sans
délai, commencez à envoyer des segments vidéo HLS. Si le serveur ne commence pas à envoyer des segments immédiatement, le joueur décidera qu'il a été trompé et arrêtera de jouer. Ce comportement est typique des lecteurs HLS natifs d'Apple, mais nous ne pouvons pas simplement dire aux utilisateurs «veuillez ne pas utiliser iPhone Mac et Apple TV pour lire les flux HLS».


Ainsi, lorsque vous essayez de lire un flux HLS sur le serveur Edge, le serveur doit immédiatement commencer à renvoyer des segments, mais comment est-il supposé le faire s'il n'a pas de flux? En effet, lorsque vous essayez de jouer, il y a
n'y a pas de flux sur ce serveur. La logique CDN fonctionne sur le principe du chargement différé - elle ne chargera pas le flux sur le serveur jusqu'à ce que quelqu'un demande ce flux sur ce serveur. Il y a un problème avec le premier connecté
utilisateur; le premier qui a demandé le flux HLS au serveur Edge et a eu l'imprudence de le faire à partir du lecteur Apple par défaut va se bloquer car il faudra un certain temps pour commander ce flux
à partir du serveur Origin, téléchargez-le sur Edge et commencez le découpage HLS. Même si cela prend trois secondes, cela n'aidera pas. Il gèlera.



Ici, nous avons deux solutions possibles: l'une est OK, et l'autre l'est moins. On pourrait abandonner l'approche Lazy Loading dans le CDN et envoyer du trafic à tous les nœuds, qu'il y ait ou non des téléspectateurs. Une solution, peut-être adaptée à ceux qui ne sont pas limités en termes de trafic et de ressources informatiques. Origin enverra du trafic vers tous les serveurs Edge, à la suite de quoi, tous les serveurs et le réseau entre eux seront constamment chargés. Ce schéma ne conviendrait peut-être qu'à certaines solutions spécifiques avec un petit nombre de flux entrants. Lors de la réplication d'un grand nombre de flux, un tel schéma sera clairement
inefficace en termes de ressources. Et si vous vous souvenez que nous ne résolvons que le «problème du premier utilisateur connecté à partir du navigateur natif», il devient clair que cela n'en vaut pas la peine.



La deuxième option est plus élégante, mais elle n'est également qu'une solution de rechange. Nous donnons au premier utilisateur connecté une image vidéo, mais ce n'est toujours pas le flux qu'il souhaite voir - c'est un préchargeur. Comme nous devons déjà leur donner quelque chose et le faire immédiatement, mais nous n'avons pas le flux source (il est toujours commandé et livré depuis Origin), nous décidons de demander au client d'attendre un peu et de lui montrer une vidéo du
préchargeur avec animation en mouvement. L'utilisateur attend quelques secondes pendant que le préchargeur tourne et lorsque le flux réel arrive enfin, l'utilisateur commence à obtenir le flux réel. En conséquence, le premier utilisateur verra le
préchargeur, et ceux qui se connectent après cela verront enfin le flux HLS régulier provenant du CDN fonctionnant sur le principe du Lazy Loading. Ainsi, le problème d'ingénierie a été résolu.


Mais pas encore complètement résolu


Il semblerait que tout fonctionne bien. Le CDN fonctionne, les flux HLS sont chargés à partir des serveurs Edge et le problème du premier utilisateur connecté est résolu. Et voici un autre écueil - nous donnons la
préchargeur dans un rapport hauteur / largeur fixe de 16: 9, tandis que les flux de n'importe quel format peuvent entrer le CDN: 16: 9, 4: 3, 2: 1 (vidéo VR). Et c'est un problème, car si vous envoyez un préchargeur au format 16: 9 au lecteur et que le flux commandé est de 4: 3, le lecteur natif sera de nouveau confronté au gel.


Par conséquent, une nouvelle tâche se pose - vous devez savoir avec quel format le flux entre dans le CDN et donner le même rapport au préchargeur. Une caractéristique des flux WebRTC est la préservation des proportions lorsque
changer la résolution et le transcodage - si le navigateur décide d'abaisser la résolution, il l'abaisse dans le même rapport. Si le serveur décide de transcoder le flux, il conserve les proportions dans la même proportion. Par conséquent, il est logique que si nous voulons afficher le préchargeur pour HLS, nous le montrons dans le même rapport d'aspect dans lequel le flux entre.



Le CDN fonctionne comme suit: lorsque le trafic pénètre dans le serveur d'origine, il informe les autres serveurs du réseau, y compris les serveurs Edge, du nouveau flux. Le problème est qu'à ce stade, la résolution de la
le flux source n'est peut-être pas encore connu. La résolution est portée par les configurations de flux binaire H.264 avec l'image clé. Par conséquent, le serveur Edge peut recevoir des informations sur un flux, mais ne connaîtra pas son
la résolution et le rapport hauteur / largeur qui ne lui permettront pas de générer correctement le préchargeur. À cet égard, il est nécessaire de signaler la présence du flux dans le CDN uniquement s'il existe une image clé - cela est garanti pour donner des informations sur la taille du serveur Edge et permettre au préchargeur correct d'être généré pour éviter «le premier problème de visionneuse connectée . "



Résumé


La conversion de WebRTC en HLS entraîne généralement un gel lors de la lecture dans les lecteurs Apple par défaut. Le problème est résolu en analysant et en ajustant le flux binaire H.264 aux exigences HLS d'Apple, soit par transcodage,
ou migrer vers le protocole RTMP et l'encodeur en tant que source de flux. Dans un réseau distribué avec chargement différé de flux, il y a le problème du premier visualiseur connecté, qui est résolu en utilisant le préchargeur et en déterminant la résolution du côté du serveur d'origine - le point d'entrée du flux dans le CDN.



Serveur d'appel Web - serveur WebRTC


CDN pour le streaming WebRTC à faible latence - CDN basé sur WCS


Lecture de flux vidéo WebRTC et RTMP via HLS - Fonctions serveur pour convertir des flux de diverses sources en HLS

Source: https://habr.com/ru/post/fr481668/


All Articles