Un stream 24/7 que no se reconecta entre vídeos: un único ffmpeg alimentado mediante una tubería

Vídeo

Un canal en directo que reproduce vídeos terminados las 24 horas tiene dos diseños sencillos, y ambos pierden algo. Reiniciar ffmpeg para cada vídeo corta la conexión RTMP en cada cambio. Una lista de reproducción concat se lee una sola vez al inicio, por lo que un vídeo nuevo espera al siguiente reinicio.

El diseño

Cada vídeo se convierte una vez a MPEG-TS con el tamaño y la frecuencia de imagen del stream; un vídeo vertical se sitúa sobre una copia desenfocada de sí mismo en lugar de barras negras. Un proceso de ffmpeg lee MPEG-TS desde su entrada estándar y codifica a tasa de bits constante con un fotograma clave cada dos segundos, como espera la ingesta en directo. Un pequeño alimentador escribe los archivos preparados en esa tubería uno tras otro, a ritmo de tiempo real, eligiendo el siguiente archivo en cada cambio: primero los vídeos nunca reproducidos, después los menos recientes. El lector de MPEG-TS de ffmpeg ve que las marcas de tiempo de cada archivo empiezan de nuevo y las desplaza, por lo que su salida continúa sin interrupciones.

Detalle uno: el ritmo desde el primer byte

Nuestra primera versión iniciaba su reloj cuando se iniciaba ffmpeg. Preparar el primer archivo tardó nueve segundos, por lo que el alimentador creía que iba nueve segundos por detrás y los enviaba todos de golpe. Iniciar el reloj en el primer byte escrito lo solucionó: una ejecución de 53 segundos produjo 53 segundos de stream.

Detalle dos: el audio en la unión

En un cambio, el audio del siguiente archivo comenzaba 17 milisegundos antes de que terminara el audio del archivo anterior. El codificador advertía que su entrada retrocedía «en el tiempo» y el multiplexador corregía una marca de tiempo. Remuestrear con aresample=async=1:min_hard_comp=0.01:first_pts=0 recorta o rellena dichas superposiciones antes de que las vea el codificador. En una ejecución de poco más de un minuto con cinco cambios, todas las marcas de tiempo de audio y vídeo del stream recibido ascendían, y el stream se decodificó sin un solo error.

Detalle tres: algunos avisos son normales

Cada archivo reinicia sus contadores MPEG-TS y su reloj, por lo que ffmpeg informa de «Packet corrupt» y «timestamp discontinuity» en cada cambio. Esas líneas son esperadas y las mantenemos fuera del registro para que destaquen los errores reales.

El watchdog

Si ffmpeg se cierra o su progreso se detiene durante un minuto, la transmisión se reinicia con pausas cada vez más largas y envía un mensaje tras varios fallos consecutivos. En nuestra prueba, detuvimos el codificador manualmente; la transmisión volvió a estar activa siete segundos después, y un vídeo añadido durante la ejecución se incorporó a la rotación sin necesidad de reconectar. Un reinicio es una reconexión breve, así que configura la transmisión de YouTube para que comience automáticamente y no se detenga automáticamente. La clave de transmisión está enmascarada en cada línea del registro, incluidas las propias de ffmpeg. Studio incluye este canal en directo como un servicio de systemd.

Actualizado: