HLS in MP4 mit ffmpeg in einem Browser

Hallo! Seit mehr als zwei Monaten säge ich in meiner Freizeit eine Webanwendung zum Konvertieren von HLS und DASH in MP4 mit emscripten und ffmpeg, von der aus ich mitteilen möchte, wie ich dies geschafft habe.

In diesem Artikel werde ich den Quellcode der ffmpeg-Änderungen und -Patches nicht als zitieren Die meisten davon wurden auf meinem Knie gemacht, und ich bin nicht sehr gut in C. Aber jetzt gibt es genug Artikel, um Ihnen zu helfen.

Einführung


Vor zwei Jahren hatte ich das Ziel, eine Audio- und eine Videospur zu einer MP4-Datei zu kombinieren. Dann habe ich mich einfach in emscripten gestürzt und für die Grundlagen das Repository ffmpeg.js gefunden, aus dem ich viel gelernt habe. Dann war ich fast in der Lage, das Ziel zu erreichen, obwohl ich in C sehr bedingt orientiert war. Als ich
den Quellcode verstand, erstellte ffmpeg einen Patch für die Arbeit mit dem Dateisystem, bei dem das Lesen aus einer Datei, die als asynchrone Funktion in js bezeichnet wurde, aus der ich den Blob der Datei las und den Puffer übergab, und als ich schrieb, rief ich an js-Funktion, die Pufferdaten an das Repository gesendet hat.

Aber es gab ein Problem mit asynchronen Funktionen, das ich nicht richtig lösen konnte. Sie arbeiteten mit asyncify (fastcomp), was in einigen Fällen nicht richtig funktionierte. Die Ausführung von Code in wasm wurde nicht gestoppt, ohne auf ein Ergebnis der js-Funktion zu warten. Das ist alles zusammengebrochen. Dieses Problem wurde über das EMTERPRETIFY_WHITELIST-Flag behoben, das den Code anscheinend gleichzeitig von wasm nach asm verschob und verlangsamte. Es war erforderlich, den Aufrufstapel zu debuggen und der Liste mit jeder Ausnahme eine fehlerhafte Funktion hinzuzufügen.

Bei solchen Problemen kann dies im Allgemeinen nicht als funktionierende Lösung bezeichnet werden, bei der dies alles eine kleine Demo blieb.



Eineinhalb Jahre später


Nachdem ich mir auf Google Dev Summit einen Bericht über neue Funktionen in WebAssambly angesehen hatte , sah ich mir an, wie es emscripten ging, und sah eine Nachricht:
Emscripten gibt WebAssembly über das Upstream-LLVM-Wasm-Backend seit Version 1.39.0 (Oktober 2019) aus, und das alte Fastcomp-Backend ist veraltet

Ich wollte versuchen, meine Repacker-Formate neu zu erstellen. Ungefähr eine Woche lang habe ich gegoogelt, wie man neue Kompilierungsprobleme behebt und schließlich alles zusammenfügt. Die Änderungen waren nicht so zahlreich, aber aufgrund des neuen Bibliothekslinkers war dies nicht der Fall. Da ich bereits verzweifelt war, zumindest etwas zu sammeln, habe ich nur die Problembibliotheken herausgesägt (wie sich herausstellte, sind die Bibliotheken selbst verbunden und müssen nicht während der Montage mit den Händen angegeben werden).

Und jetzt ist der Moment gekommen, in dem es sich versammelt und verdient hat! Das Problem mit dem asynchronen Code war verschwunden, es war nicht nötig, irgendetwas zu debuggen, es funktionierte von Anfang an so, wie es sollte.

Hier scheine ich mein Ziel erreicht zu haben, aber ... ein neues erschien.

Schreiben Sie das HTTP-Protokoll neu


Ein solcher Gedanke ist mir schon lange in den Sinn gekommen. Auf diese Weise können Sie HLS oder DASH herunterladen und nicht nur eine vorgefertigte Wiedergabeliste, sondern auch einen Live-Stream. Und so etwas habe ich noch nie im Internet gesehen.

Ich habe ungefähr drei Wochen gebraucht, um mit kurzen Pausen zumindest etwas mit mir zu machen. Ich kannte C (obwohl ich keine Erfahrung hatte), es gab viele Probleme mit Zeigern (es ist schwierig zu verfolgen, wohin es geht, und sogar im Code eines anderen), aber schließlich wurde etwas ohne Fehler kompiliert. Nach den ersten Erfolgen gab dies noch mehr Begeisterung, um die Idee zu vervollständigen.

Nur ein paar Wochen, und schließlich habe ich es geschafft, die erste Iteration des funktionierenden http-Protokolls durchzuführen, und das scheint alles zu sein?

Wenn das Schwierigste vorbei ist


Zu diesem Zeitpunkt hatte ich ein Framework bereit, ein kleines HTML-Formular mit einem URL-Eingabefeld und einer Startschaltfläche, im Grunde funktionierte es. Es war jedoch weiterhin erforderlich, eine Erweiterung zu schreiben, um CORS zu umgehen und Daten zu laden, einen Speicher zu erstellen, der Daten in Blöcken schreibt, eine Schnittstelle mit Fortschrittsanzeige zu erstellen. All dies wurde getestet, um Probleme in verschiedenen Browsern zu beheben. Im Allgemeinen ist es an der Zeit, es endlich möglich zu machen, es zu benutzen.

Grundsätzlich wurde Userscript erstellt, das ein Proxy für Abrufanforderungen von ffmpeg zum Herunterladen von Daten war.

Ein paar Tage später war eine Erweiterung für Chrome und Firefox fertig, die mithilfe von webRequest alle hls-Links sammelte, die der Browser beim Ansehen eines Videos lädt.

Wie sich herausstellte, können Sie in Firefox mit der Erweiterungs-API die Stromversorgung nicht verwalten, wodurch Sie leider nicht verhindern können, dass der Computer einschlafen kann.

Die Erweiterung sieht folgendermaßen aus:



Nur die Seite, auf der sich die Site befand, wurde ein wenig verbessert, Material-UI verschraubt und alle Stellen fertiggestellt, die ausgepeitscht wurden.



Nachdem ich verschiedene Methoden zum Speichern von Daten getestet hatte, stellte ich eine Reihe von Problemen fest:

Blob - Chrome schreibt sie in den Arbeitsspeicher und legt sie auf der Festplatte ab, wenn sie überläuft. Unter OSX verlässt das Betriebssystem das Konto und schließt alle geöffneten Anwendungen, wenn der Speicher überläuft. Und Firefox hat im Allgemeinen immer Daten im Speicher gespeichert.

Cache-Speicher- Es funktioniert wie IndexedDb, aber nach dem Schreiben von Daten verbleiben sie im Chrome-Blob im RAM (entweder ein Fehler oder ein Fitcha). Es stellt sich jedoch heraus, dass die Daten in den Cache-Speicher (auf die Festplatte) geschrieben werden und auch dann gelöscht werden, wenn der Speicher voll ist Volume auf Festplatte als Blob.

IndexedDb - funktioniert wie eine Uhr, kann Blob speichern, schreibt Daten ohne Schnickschnack, aber Firefox begrenzt die Menge von 2 GB streng.

Ich habe es ein wenig fertiggestellt, es ist mir gelungen, den ffmpeg-Prozess (über einen Zeiger) zu unterbrechen. Ich habe mir überlegt, wie man eine Auswahl an Formaten (ffprobe) trifft und Netzwerkfehler behandelt.





Und jetzt können Sie das Ergebnis hier selbst ausprobieren

Für mich ist dies eine unverzichtbare Sache, wenn Sie einen Stream auf einem Tweet aufnehmen oder einen VOD herunterladen müssen. Es funktioniert auch mit einem Laptop, einem Mixer und anderen Sites, die Inhalte in HLS oder DASH senden (leider ist die DASH-Implementierung in ffmpeg sehr bedingt und wird möglicherweise nicht korrekt heruntergeladen, da das Fragmentanforderungsintervall nicht berücksichtigt wird).

Danke fürs Lesen!

Wenn Sie Fragen zu ffmpeg und emscripten - write haben, werde ich versuchen, diese zu beantworten.

All Articles