Um stream 24/7 que não se reconecta entre vídeos: um único ffmpeg alimentado por um pipe
Vídeo
Um canal ao vivo que reproduz vídeos finalizados o dia todo tem dois designs simples, e ambos perdem algo. Reiniciar o ffmpeg para cada vídeo derruba a conexão RTMP a cada troca. Uma playlist concat é lida uma vez no início, então um novo vídeo espera pelo próximo reinício.
O design
Cada vídeo é convertido uma vez em MPEG-TS no tamanho e taxa de quadros do stream; um vídeo vertical fica sobre uma cópia desfocada de si mesmo em vez de barras pretas. Um único processo ffmpeg lê MPEG-TS de sua entrada padrão e codifica com bitrate constante e um keyframe a cada dois segundos, como o ingest ao vivo espera. Um pequeno feeder escreve os arquivos preparados nesse pipe, um após o outro, em tempo real, escolhendo o próximo arquivo a cada troca: vídeos nunca reproduzidos primeiro, depois os menos recentemente reproduzidos. O leitor MPEG-TS do ffmpeg vê que os timestamps de cada arquivo recomeçam e os desloca, então sua saída roda sem interrupção.
Detalhe um: ritmo a partir do primeiro byte
Nossa primeira versão iniciava o relógio quando o ffmpeg iniciava. Preparar o primeiro arquivo levou nove segundos, então o feeder achou que estava nove segundos atrasado e enviou tudo de uma vez. Iniciar o relógio no primeiro byte escrito resolveu: uma execução de 53 segundos produziu 53 segundos de stream.
Detalhe dois: o áudio na junção
Em uma troca, o áudio do próximo arquivo começou 17 milissegundos antes do áudio do arquivo anterior terminar. O codificador alertou que sua entrada ia "para trás no tempo" e o muxer corrigiu um timestamp. Remostrar com aresample=async=1:min_hard_comp=0.01:first_pts=0 corta ou preenche essas sobreposições antes que o codificador as veja. Em uma execução de pouco mais de um minuto com cinco trocas, todos os timestamps de áudio e vídeo no stream recebido subiram, e o stream decodificou sem um único erro.
Detalhe três: alguns avisos são normais
Cada arquivo reinicia seus contadores MPEG-TS e seu relógio, então o ffmpeg reporta "Packet corrupt" e "timestamp discontinuity" a cada troca. Essas linhas são esperadas, e as mantemos fora do log para que erros reais se destaquem.
O watchdog
Se o ffmpeg encerrar ou seu progresso parar por um minuto, a transmissão reinicia com pausas crescentes e envia uma mensagem após falhas repetidas. Em nosso teste, encerramos o codificador manualmente; a transmissão voltou sete segundos depois, e um vídeo adicionado durante a execução entrou na rotação sem reconexão. Uma reinicialização é uma reconexão curta, então configure a transmissão no YouTube para iniciar automaticamente e não parar automaticamente. A chave de transmissão é mascarada em todas as linhas de log, incluindo as do próprio ffmpeg. O Studio oferece este canal ao vivo como um serviço systemd.