HLS en MP4 usando ffmpeg en un navegador

隆Hola! Durante m谩s de dos meses, en mi tiempo libre, he estado guardando una aplicaci贸n web para convertir HLS y DASH a MP4 usando emscripten y ffmpeg, desde la cual quiero compartir c贸mo logr茅 hacer esto.

En este art铆culo no citar茅 el c贸digo fuente de las ediciones y parches de ffmpeg, como la mayor铆a de ellos se hicieron sobre mi rodilla, y no soy muy bueno en C. Pero ahora hay suficientes art铆culos para ayudarte.

Introducci贸n


Hace dos a帽os ten铆a el objetivo de combinar una pista de audio y video en un solo archivo mp4. Luego me sumerg铆 en emscripten y, para lo b谩sico, encontr茅 el repositorio ffmpeg.js del cual aprend铆 mucho. Luego, casi pude lograr el objetivo, aunque estaba muy orientado condicionalmente en C.
Comprendiendo el c贸digo fuente, ffmpeg hizo un parche para trabajar con el sistema de archivos, donde la lectura de un archivo causaba una funci贸n asincr贸nica en js desde la cual le铆a el blob del archivo y pasaba el b煤fer, y al escribir, Funci贸n js que envi贸 datos de b煤fer al repositorio.

Pero hubo un problema con las funciones asincr贸nicas, que no pude resolver correctamente, funcionaron a trav茅s de asyncify (fastcomp), que no funcion贸 correctamente en algunos casos, a saber, la ejecuci贸n del c贸digo en wasm no se detuvo, sin esperar un resultado de la funci贸n js, eso es todo rompi贸. Este problema se solucion贸 mediante el indicador EMTERPRETIFY_WHITELIST, que aparentemente movi贸 el c贸digo de wasm a asm al mismo tiempo y lo ralentiz贸, y fue necesario depurar la pila de llamadas y agregar una funci贸n rota a la lista con cada excepci贸n.

En general, con tales problemas, esto no podr铆a llamarse una soluci贸n de trabajo, en la que todo esto segu铆a siendo una peque帽a demostraci贸n.



Un a帽o y medio despu茅s


Despu茅s de ver un informe en Google Dev Summit sobre las nuevas caracter铆sticas en WebAssambly , fui a ver c贸mo estaba emscripten y vi un mensaje:
Emscripten emite WebAssembly utilizando el back-end de wasm LLVM ascendente, desde la versi贸n 1.39.0 (octubre de 2019), y el antiguo backend fastcomp est谩 en desuso

Quer铆a intentar reconstruir mis formatos de repacker. Aproximadamente una semana busqu茅 en Google c贸mo solucionar nuevos problemas de compilaci贸n y finalmente lo arm茅 todo. Los cambios no fueron tantos, pero no fue as铆 debido al nuevo enlazador de bibliotecas, y ya desesperado por recopilar al menos algo, acabo de ver las bibliotecas problem谩ticas (result贸 que las bibliotecas est谩n conectadas y ya no es necesario se帽alarlas a mano durante el ensamblaje).

隆Y ahora, ha llegado el momento en que se ha reunido y ganado! El problema con el c贸digo asincr贸nico desapareci贸, no hab铆a necesidad de depurar nada, funcion贸 como deber铆a desde el principio.

Aqu铆 parece que he alcanzado mi objetivo, pero ... apareci贸 uno nuevo.

Reescribir protocolo HTTP


Tal pensamiento ha estado en mi mente durante mucho tiempo. Esto puede permitirle descargar HLS o DASH, y no solo una lista de reproducci贸n lista para usar, sino tambi茅n una transmisi贸n en vivo. Y nunca he visto algo as铆 en Internet.

Me llev贸 unas tres semanas hacer al menos algo que funcionara conmigo con breves descansos. Conoc铆a C (aunque no ten铆a experiencia), hab铆a muchos problemas con los punteros (es dif铆cil hacer un seguimiento de a d贸nde va, e incluso en el c贸digo de otra persona), pero algo se compil贸 sin errores. Despu茅s de los primeros 茅xitos, esto dio a煤n m谩s entusiasmo para completar la idea.

Solo un par de semanas, y finalmente logr茅 hacer la primera iteraci贸n del protocolo http en funcionamiento, 驴y eso parece ser todo?

Cuando lo m谩s dif铆cil ha terminado


En este punto, ten铆a un marco listo, un peque帽o formulario html con un campo de entrada de URL y un bot贸n de inicio, b谩sicamente funcion贸. Pero a煤n era necesario escribir una extensi贸n para evitar CORS y cargar datos, hacer un almacenamiento que escribiera datos en fragmentos, hacer una interfaz con pantalla de progreso, todo esto se depur贸 para solucionar problemas en diferentes navegadores. En general, ha llegado el momento de finalmente hacer posible su uso.

B谩sicamente, se realiz贸 el script de usuario, que era un proxy para buscar solicitudes de ffmpeg para descargar datos.

En solo un par de d铆as, estaba lista una extensi贸n para Chrome y Firefox, que mediante webRequest recopil贸 todos los enlaces hls que carga el navegador cuando mira un video.

Como result贸, en Firefox, la API de extensi贸n no le permite administrar la energ铆a, desde la cual no puede evitar que la computadora se duerma, por desgracia.

La extensi贸n se ve as铆:



solo mejor茅 la p谩gina en la que el sitio era un poco, material de interfaz de usuario atornillado, finalic茅 todos los lugares que se crearon.



Despu茅s de probar diferentes formas de almacenar datos, revel茅 una serie de problemas:

Blob : Chrome los escribe en la RAM y los deja caer en el disco cuando se desborda, pero solo en OSX cuando se desborda la memoria, el sistema operativo abandona la cuenta y cierra todas las aplicaciones que estaban abiertas. Y Firefox generalmente siempre guardaba datos en la memoria.

Almacenamiento en cach茅- funciona como IndexedDb, pero despu茅s de escribir los datos, en Chrome blob permanecen en la RAM (ya sea un error o un fitcha), pero resulta que los datos se escriben en el almacenamiento en cach茅 (en el disco) y tambi茅n se caen cuando la memoria est谩 llena volumen al disco como blob.

IndexedDb : funciona como un reloj, sabe c贸mo almacenar blobs, escribe datos sin adornos, pero Firefox limita estrictamente la cantidad de 2 gb.

Trabaj茅 un poco, logr茅 hacer la funci贸n de interrumpir el proceso ffmpeg (a trav茅s de un puntero), se me ocurri贸 c贸mo elegir los formatos (ffprobe) y manejar los errores de la red.





Y ahora, puedes probar el resultado t煤 mismo aqu铆

Para m铆, esto es algo indispensable cuando necesitas grabar una transmisi贸n en un tweet o descargar un VOD. Tambi茅n funciona con una computadora port谩til, un mezclador y cualquier otro sitio que transmita contenido en HLS o DASH (por desgracia, la implementaci贸n de DASH en ffmpeg es muy condicional y es posible que Live no se descargue correctamente, ya que no tiene en cuenta el intervalo de solicitud de fragmento).

隆Gracias por leer!

Si tiene preguntas sobre ffmpeg y emscripten, escriba, intentar茅 responder.

All Articles