Das erste Problem mit dem Viewer oder die Schwierigkeiten beim Konvertieren von WebRTC-Videostreams in HLS


George schloss seinen Laptop und rieb sich die roten Augen. "Kunden beschweren sich weiterhin über das Einfrieren von Streams. Das neue Fix-Paket hat überhaupt nicht geholfen. Was mache ich mit diesem (zensierten) HLS?" sagte er.


Der Browser ist nicht nur Hypertext, sondern auch ein Streamer


Browser haben schon lange Player, aber die Geschichte ist anders mit dem Video-Encoder und dem Streaming. Jetzt können wir in fast jedem Browser der neuesten Version Module zum Codieren, Streamen, Decodieren und Wiedergeben finden. Diese Funktionen sind über die JavaScript-API verfügbar, und die Implementierung wird als Web Real Time Communications oder WebRTC bezeichnet. Diese in Browser integrierte Bibliothek kann eine ganze Menge: Videos von einer integrierten, virtuellen oder USB-Kamera aufnehmen, mit den H.264-, VP8- und VP9-Codecs komprimieren und über das SRTP-Protokoll an das Netzwerk senden. Das heißt, es fungiert als Software-Streamer-Video-Encoder. Als Ergebnis sehen wir einen Browser, der etwas ähnliches wie ffmpeg oder gstreamer hat, Video gut komprimiert, Streams auf RTP und Video-Streams wiedergibt.


Mit WebRTC können wir eine Vielzahl von Streaming-Fällen in JavaScript implementieren:


  • Stream vom Browser zum Server zur Aufzeichnung und anschließenden Verteilung
  • Peer-to-Peer-Streams verteilen
  • Spiele den Stream eines anderen Benutzers ab und sende den eigenen (Video-Chat)
  • Konvertieren Sie andere Protokolle vom Server, z. B. RTMP, RTSP usw., und spielen Sie sie im Browser als WebRTC ab

Verbesserte Flusskontrollskripte könnten so aussehen:


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

HLS funktioniert dort, wo WebRTC nicht funktioniert


WebRTC wird in den neuesten Versionen von Browsern ausgeführt. Es gibt jedoch die folgenden zwei Faktoren: 1) Nicht alle Nutzer aktualisieren ihre Browser rechtzeitig und verwenden möglicherweise die alte Version von Chrome drei Jahre lang. 2) Updates und neue Browser, WebView sowie andere Clients und Instant Messenger, die Benutzern das Surfen im Internet erleichtern, werden fast einmal pro Woche veröffentlicht. Es ist unnötig zu erwähnen, dass nicht alle von ihnen WebRTC-Unterstützung haben, und falls doch, kann dies eingeschränkt sein. Sehen Sie, wie es jetzt ist:



Die Lieblingsgeräte von Apple können Kopfschmerzen bereiten. Sie haben erst vor kurzem damit begonnen, WebRTC zu unterstützen, und manchmal scheint ihr Verhalten im Vergleich zu Webkit-Browsern überraschend. Wenn WebRTC nicht oder nicht sehr gut funktioniert, funktioniert HLS einwandfrei. In dieser Hinsicht ist Kompatibilität erforderlich und so etwas wie ein Konverter, mit dem wir WebRTC in HLS konvertieren und auf fast jedem Gerät abspielen können.


HLS war ursprünglich nicht für Echtzeit-Streams konzipiert. Wie können wir Echtzeitvideos über HTTP streamen? Die Aufgabe von HLS ist es, das Video in Stücke zu schneiden und es ruckelfrei an den Player zu liefern, indem Sie es nacheinander herunterladen. Ein HLS-Player erwartet einen streng geformten und reibungslosen Videostream. Hier besteht ein Konflikt, da es sich WebRTC im Gegenteil leisten kann, Pakete aufgrund von Echtzeitanforderungen und geringer Latenzzeit zu verlieren und eine schwebende FPS / GOP und eine variable Bitrate zu haben - in Bezug auf die Vorhersagbarkeit das genaue Gegenteil von HLS und Regelmäßigkeit des Stroms.


Ein naheliegender Ansatz: Die WebRTC-Depaketisierung (SRTP) und die anschließende Konvertierung in HLS funktionieren möglicherweise nicht in einem systemeigenen HLS-Player von Apple oder arbeiten mit Freezing, einer für die Produktion ungeeigneten Form. Der native Player ist ein Player, der in Apple iOS Safari, Mac OS Safari und Apple TV verwendet wird.


Wenn Sie feststellen, dass HLS im nativen Player einfriert, ist dies möglicherweise der Fall, und die Quelle des Streams ist WebRTC oder ein anderer dynamischer Stream mit ungleichmäßigem Markup. Darüber hinaus gibt es bei der Implementierung der nativen Apple-Player ein Verhalten, das nur empirisch verstanden werden kann. Beispielsweise sollte der Server sofort nach der Rückgabe der m3u8-Wiedergabeliste mit dem Senden von HLS-Segmenten beginnen. Eine Verzögerung von 1 Sekunde kann zum Einfrieren führen. Wenn sich die Bitstream-Konfiguration während des Vorgangs ändert (was beim WebRTC-Streaming häufig vorkommt), kommt es ebenfalls zum Einfrieren.


Kampf gegen das Einfrieren bei einheimischen Spielern


Daher funktionieren die WebRTC-Depaketisierung und die HLS-Paketierung im Allgemeinen nicht. Beim Streaming-Videoserver Web Call Server (WCS) lösen wir das Problem auf zwei Arten und bieten die dritte als Alternative an:


1) Umcodierung.


Dies ist die zuverlässigste Methode, um einen WebRTC-Stream an HLS-Anforderungen anzupassen, die gewünschte GOP, FPS usw. festzulegen. In einigen Fällen ist das Umcodieren jedoch keine gute Lösung. Zum Beispiel das Transcodieren von 4k-Streams
von VR Video ist in der Tat eine schlechte Idee. Solche gewichtigen Streams sind in Bezug auf CPU-Zeit oder GPU-Ressourcen sehr teuer in der Transcodierung.



2) Anpassen und Ausrichten des WebRTC-Flusses für unterwegs, um den HLS-Anforderungen zu entsprechen.


Hierbei handelt es sich um spezielle Parser, die den H.264-Bitstream analysieren und an die Funktionen / Fehler der nativen HLS-Player von Apple anpassen. Zugegebenermaßen sind nicht native Player wie video.js und hls.js toleranter gegenüber Streams
mit einer dynamischen Bitrate und FPS, die auf WebRTC ausgeführt werden, und verlangsamen Sie nicht, wenn die Referenzimplementierung von Apple HLS im Wesentlichen zum Einfrieren führt.



3) Verwenden von RTMP als Stream-Quelle anstelle von WebRTC.


Obwohl Flash Player bereits veraltet ist, wird das RTMP-Protokoll aktiv für das Streaming verwendet. Nehmen Sie zum Beispiel OBS Studio. Wir müssen anerkennen, dass RTMP-Encoder im Allgemeinen gleichmäßiger produzieren
Streams als WebRTC verursachen praktisch kein Einfrieren in HLS, d. h. eine RTMP> HLS-Konvertierung scheint im Hinblick auf das Einfrieren viel geeigneter zu sein, auch in nativen HLS-Playern. Deshalb, wenn Streaming ist
Wenn Sie den Desktop und OBS verwenden, ist es besser, ihn für die Konvertierung in HLS zu verwenden. Wenn die Quelle der Chrome-Browser ist, kann RTMP nicht ohne die Installation von Plugins verwendet werden, und in diesem Fall funktioniert nur WebRTC.



Alle drei oben beschriebenen Methoden wurden getestet und funktionieren, sodass Sie sie je nach Aufgabe auswählen können.


WebRTC zu HLS auf CDN


Es gibt einige unerwünschte Ereignisse, die in einem verteilten System auftreten können, wenn sich zwischen der WebRTC-Stream-Quelle und dem HLS-Player, in unserem Fall CDN , basierend auf einem WCS-Server, mehrere WebRTC-Stream-Delivery-Server befinden. Es sieht so aus: Es gibt Origin - einen Server, der WebRTC-Stream akzeptiert, und es gibt Edge-Server, die diesen Stream auch über HLS verteilen. Es können viele Server vorhanden sein, was eine horizontale Skalierung des Systems ermöglicht. Beispielsweise können 1000 HLS-Server mit einem Origin-Server verbunden werden. In diesem Fall wird die Systemkapazität 1000-mal skaliert.



Das Problem ist bereits oben hervorgehoben worden; Dies tritt normalerweise bei nativen Playern auf: iOS Safari, Mac OS Safari und Apple TV. Mit native meinen wir einen Player, der mit einer direkten Anzeige der Playlist-URL arbeitet
das Tag, zum Beispiel <video src="https://host/test.m3u8"/> . Sobald der Spieler eine Wiedergabeliste angefordert hat - und diese Aktion ist eigentlich der erste Schritt beim Abspielen des HLS-Streams - muss der Server sofort darauf verzichten
Verzögerung, beginnen Sie HLS-Videosegmente auszusenden. Wenn der Server nicht sofort beginnt, Segmente zu senden, entscheidet der Player, dass er betrogen wurde, und beendet die Wiedergabe. Dieses Verhalten ist typisch für native HLS-Player von Apple, aber wir können den Nutzern nicht nur sagen, dass sie zum Abspielen von HLS-Streams kein iPhone, keinen Mac oder Apple TV verwenden sollen.


Wenn Sie also versuchen, einen HLS-Stream auf dem Edgeserver abzuspielen, sollte der Server sofort beginnen, Segmente zurückzugeben. Wie soll er dies tun, wenn er keinen Stream hat? In der Tat, wenn Sie versuchen, es zu spielen, gibt
ist kein Stream auf diesem Server. Die CDN-Logik funktioniert nach dem Prinzip des verzögerten Ladens - der Stream wird erst auf den Server geladen, wenn jemand diesen Stream auf diesem Server anfordert. Es ist ein Problem des ersten verbunden
Benutzer; Der erste Benutzer, der den HLS-Stream vom Edge-Server angefordert hat und die Unklugheit hatte, dies über den Standard-Apple-Player zu tun, friert ein, da die Bestellung dieses Streams einige Zeit in Anspruch nimmt
Rufen Sie es vom Origin-Server auf Edge ab und beginnen Sie mit dem HLS-Slicing. Auch wenn es drei Sekunden dauert, hilft dies nicht. Es wird einfrieren.



Hier haben wir zwei mögliche Lösungen: Eine ist in Ordnung und die andere weniger. Man könnte den Lazy Loading-Ansatz im CDN aufgeben und Datenverkehr an alle Knoten senden, unabhängig davon, ob es Zuschauer gibt oder nicht. Eine Lösung, die möglicherweise für diejenigen geeignet ist, die in Bezug auf Verkehr und Rechenressourcen keine Einschränkungen aufweisen. Origin sendet Datenverkehr an alle Edgeserver, wodurch alle Server und das Netzwerk zwischen ihnen ständig geladen werden. Vielleicht wäre dieses Schema nur für einige spezifische Lösungen mit einer kleinen Anzahl von eingehenden Flüssen geeignet. Bei der Replikation einer großen Anzahl von Streams ist ein solches Schema eindeutig
ineffizient in Bezug auf Ressourcen. Und wenn Sie sich daran erinnern, dass wir nur das „Problem des ersten verbundenen Benutzers im nativen Browser“ lösen, wird klar, dass es sich nicht lohnt.



Die zweite Option ist eleganter, aber es ist auch nur ein Ende. Wir geben dem ersten verbundenen Benutzer ein Videobild, aber dies ist immer noch nicht der Stream, den er sehen möchte - dies ist ein Preloader. Da wir ihnen bereits etwas geben müssen und es sofort tun müssen, aber wir nicht über den Quelldatenstrom verfügen (dieser wird noch von Origin bestellt und geliefert), bitten wir den Kunden, etwas zu warten und ihnen ein Video des zu zeigen
Preloader mit bewegter Animation. Der Benutzer wartet einige Sekunden, während sich der Preloader dreht, und wenn der reale Stream endlich kommt, beginnt der Benutzer, den realen Stream abzurufen. Infolgedessen sieht der erste Benutzer die
preloader und diejenigen, die sich danach verbinden, werden endlich den regulären HLS-Stream vom CDN sehen, der nach dem Prinzip des Lazy Loading arbeitet. Damit ist das Engineering-Problem gelöst.


Aber noch nicht vollständig gelöst


Es scheint, dass alles gut funktioniert. Das CDN funktioniert, die HLS-Streams werden von den Edgeservern geladen und das Problem des ersten verbundenen Benutzers ist behoben. Und hier ist eine weitere Falle - wir geben die
Preloader in einem festen Seitenverhältnis von 16: 9, während Streams aller Formate in das CDN: 16: 9, 4: 3, 2: 1 (VR-Video) eingegeben werden können. Und das ist ein Problem, denn wenn Sie einen Preloader im 16: 9-Format an den Player senden und der bestellte Stream 4: 3 ist, wird der native Player erneut vor dem Einfrieren stehen.


Daher entsteht eine neue Aufgabe: Sie müssen wissen, mit welchem ​​Seitenverhältnis der Stream in das CDN eingeht, und dem Preloader dasselbe Verhältnis zuweisen. Ein Merkmal von WebRTC-Streams ist die Beibehaltung des Seitenverhältnisses bei
Ändern der Auflösung und der Umcodierung - Wenn der Browser die Auflösung verringert, verringert er sie im gleichen Verhältnis. Wenn der Server beschließt, den Stream zu transkodieren, behält er das Seitenverhältnis im gleichen Verhältnis bei. Daher ist es sinnvoll, den Preloader für HLS in demselben Seitenverhältnis anzuzeigen, in dem der Stream eingeht.



Das CDN funktioniert folgendermaßen: Wenn Datenverkehr auf den Origin-Server gelangt, werden andere Server im Netzwerk, einschließlich Edgeserver, über den neuen Stream informiert. Das Problem ist, dass an dieser Stelle die Auflösung des
Quellstream ist möglicherweise noch nicht bekannt. Die Auflösung wird von den H.264-Bitstream-Konfigurationen zusammen mit dem Schlüsselbild übernommen. Daher empfängt der Edgeserver möglicherweise Informationen zu einem Stream, weiß jedoch nichts über den Stream
Auflösung und Seitenverhältnis, wodurch der Preloader nicht korrekt generiert werden kann. In diesem Zusammenhang ist es nur erforderlich, das Vorhandensein des Streams im CDN zu signalisieren, wenn ein Schlüsselframe vorhanden ist. Dies gibt garantiert die Informationen zur Größe des Edge-Servers an und ermöglicht die Generierung des richtigen Preloaders, um ein Problem mit dem ersten verbundenen Viewer zu vermeiden . "



Zusammenfassung


Das Konvertieren von WebRTC in HLS führt in der Regel zu einem Einfrieren, wenn es in Apple-Standardplayern abgespielt wird. Das Problem wird gelöst, indem der H.264-Bitstream analysiert und an die HLS-Anforderungen von Apple angepasst wird.
oder Migration auf das RTMP-Protokoll und den Encoder als Stream-Quelle. In einem verteilten Netzwerk mit Lazy Loading von Streams besteht das Problem des ersten verbundenen Viewers, der mithilfe des Preloaders gelöst wird und die Auflösung auf der Origin-Serverseite bestimmt - dem Eintrittspunkt des Streams im CDN.



Webanrufserver - WebRTC-Server


CDN für WebRTC-Streaming mit geringer Latenz - WCS-basiertes CDN


Wiedergabe von WebRTC- und RTMP-Videostreams über HLS - Serverfunktionen zum Konvertieren von Streams aus verschiedenen Quellen in HLS

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


All Articles