Круглосуточный поток без переподключения между видео: один 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.

Обновлено: