Круглосуточный поток без переподключения между видео: один ffmpeg, подаваемый через pipe
Видео
У круглосуточного канала, воспроизводящего готовые видео, есть два простых варианта, и оба чем-то жертвуют. Перезапуск ffmpeg для каждого видео разрывает RTMP-соединение при каждом переключении. Плейлист concat считывается один раз при запуске, поэтому новое видео ждет следующего перезапуска.
Решение
Каждое видео один раз конвертируется в MPEG-TS с разрешением и частотой кадров потока; вертикальное видео помещается на размытую копию самого себя вместо черных полос. Один процесс ffmpeg читает MPEG-TS из стандартного ввода и кодирует с постоянным битрейтом, вставляя ключевой кадр каждые две секунды, как того ожидает live-приемник. Небольшой подкачиватель записывает подготовленные файлы в этот pipe один за другим в реальном времени, выбирая следующий файл при каждом переключении: сначала видео, которые еще не воспроизводились, затем наименее недавно воспроизводившиеся. Читатель MPEG-TS в ffmpeg видит, что таймкоды каждого файла начинаются заново, и сдвигает их, так что его выходной поток идет без разрывов.
Деталь 1: темп от первого байта
Наша первая версия запускала отсчет времени при старте ffmpeg. Подготовка первого файла заняла девять секунд, поэтому подкачиватель решил, что отстал на девять секунд, и отправил их все сразу. Запуск отсчета времени с момента записи первого байта исправил проблему: запуск на 53 секунды дал 53 секунды потока.
Деталь 2: звук на стыке
При переключении аудио следующего файла начиналось на 17 миллисекунд раньше, чем заканчивалось аудио предыдущего файла. Кодировщик предупреждал, что его вход «идет назад во времени», а мультиплексор исправлял таймкод. Ресемплинг с aresample=async=1:min_hard_comp=0.01:first_pts=0 обрезает или дополняет такие наложения до того, как их увидит кодировщик. В запуске чуть более минуты с пятью переключениями все таймкоды аудио и видео в полученном потоке возрастали, и поток декодировался без единой ошибки.
Деталь 3: некоторые предупреждения нормальны
Каждый файл сбрасывает свои счетчики MPEG-TS и часы, поэтому ffmpeg сообщает «Packet corrupt» и «timestamp discontinuity» при каждом переключении. Эти строки ожидаемы, и мы убираем их из журнала, чтобы реальные ошибки выделялись.
The watchdog
Если ffmpeg завершится или его прогресс остановится на минуту, трансляция перезапускается с нарастающими паузами и отправляет сообщение после повторяющихся сбоев. В нашем тесте мы вручную убили энкодер; трансляция вернулась через семь секунд, а видео, добавленное во время работы, присоединилось к ротации без переподключения. Перезапуск — это короткое переподключение, поэтому настройте запуск трансляции на YouTube на автоматический старт и отключите автоматическую остановку. Ключ трансляции маскируется в каждой строке журнала, включая строки самого ffmpeg. Studio поставляет этот прямой канал как службу systemd.