06-04-01 Мультивью: мозаика из нескольких RTSP-источников

В современных видеокомплексах — будь то студийный пульт, система видеонаблюдения или видеостена — часто возникает необходимость одновременно отображать изображение с нескольких камер. Одним из наиболее эффективных и технически доступных решений для этого является создание мозаики (multiview mosaic) с использованием FFMPEG. Этот подход позволяет объединить несколько видеопотоков в одно выходное видео, где каждый источник занимает выделенную область кадра, например, в виде сетки 2×2.
Такой формат особенно полезен для:
- Оперативных пультов, где требуется обзор с нескольких точек;
- Студийных preview, чтобы контролировать сцену с разных ракурсов;
- Видеостен, где важно визуально компактно представить множество источников.
Рассмотрим, как реализуется такая задача на практике с помощью FFMPEG, и какие технические нюансы при этом необходимо учитывать.
Команда FFMPEG для создания мозаики 2×2
Приведённая ниже команда демонстрирует типичный сценарий создания мозаики из четырёх RTSP-источников:
ffmpeg -i rtsp://cam1 -i rtsp://cam2 -i rtsp://cam3 -i rtsp://cam4 \
-filter_complex "\
[0:v]setpts=PTS-STARTPTS,scale=640x360[cam1];\
[1:v]setpts=PTS-STARTPTS,scale=640x360[cam2];\
[2:v]setpts=PTS-STARTPTS,scale=640x360[cam3];\
[3:v]setpts=PTS-STARTPTS,scale=640x360[cam4];\
[cam1][cam2][cam3][cam4]xstack=inputs=4:layout=0_0|640_0|0_360|640_360[out]" \
-map "[out]" -c:v libx264 -f flv rtmp://server/app/mosaic
Разберём её по частям, чтобы понять логику работы.
Этапы обработки: от источников к финальному кадру
1. Подключение к RTSP-источникам
Каждый из четырёх -i rtsp://... указывает FFMPEG на отдельный видеопоток с IP-камеры. FFMPEG одновременно инициирует подключение к каждому источнику, начинает приём RTP-пакетов и их демультиплексацию. Это требует от системы:
- стабильного сетевого соединения с каждой камерой;
- достаточной пропускной способности канала;
- устойчивости к возможным флуктуациям задержки (jitter) в сети.
⚠️ Важно: если одна из камер не отвечает или теряет соединение, FFMPEG по умолчанию может остановить всю команду. В реальных системах это решается обёртыванием в скрипты с перезапуском или использованием опций вроде
-timeoutи-reconnect.
2. Обработка каждого видеопотока: выравнивание времени и масштабирование
Перед объединением видео необходимо привести все потоки к единому формату и временной шкале. Это достигается с помощью цепочки фильтров:
[0:v]setpts=PTS-STARTPTS,scale=640x360[cam1]
Разберём этот фрагмент:
[0:v]— ссылка на видеопоток первого входа (камера 1);setpts=PTS-STARTPTS— сбрасывает временную метку (PTS), чтобы отсчёт шёл с нуля. Это критически важно, потому что разные камеры могут иметь разную начальную задержку, и их временные шкалы не синхронизированы;scale=640x360— изменяет разрешение кадра до нужного размера, чтобы все потоки занимали одинаковую площадь в мозаике;[cam1]— присваивает результат метке, чтобы использовать её далее в цепочке.
То же самое повторяется для остальных трёх источников. Без setpts возможна рассинхронизация — один поток может "прыгать" во времени относительно других, что приведёт к визуальным артефактам или ошибкам при кодировании.
3. Объединение потоков: фильтр xstack
После подготовки всех четырёх видеопотоков они объединяются с помощью фильтра xstack:
[cam1][cam2][cam3][cam4]xstack=inputs=4:layout=0_0|640_0|0_360|640_360[out]
Здесь:
inputs=4— указывает, что объединяется четыре входа;layoutзадаёт расположение каждого источника в финальном кадре:0_0— левый верхний угол (камера 1);640_0— правый верхний (камера 2);0_360— левый нижний (камера 3);640_360— правый нижний (камера 4).
Финальное изображение будет иметь размер 1280×720 (640×2 на ширину, 360×2 на высоту), что соответствует стандартному HD-формату.
💡 Примечание:
xstack— более современная и гибкая альтернатива устаревшемуtile. Он поддерживает произвольные позиции и даже перекрытия, в отличие от строгой сетки.
4. Вывод результата
-map "[out]" -c:v libx264 -f flv rtmp://server/app/mosaic
-map "[out]"— указывает, что выходной видеопоток берётся из результата фильтраxstack;-c:v libx264— кодирует объединённое видео в H.264;-f flv— упаковывает поток в контейнер FLV, совместимый с RTMP;rtmp://server/app/mosaic— адрес назначения, например, медиасервер (Wowza, Nginx-RTMP, OBS).
Ключевые технические аспекты
1. Выравнивание временных меток (setpts)
Разные камеры могут:
- иметь разную начальную задержку;
- использовать разные часы (clock drift);
- передавать поток с разным буфером на стороне камеры.
Без setpts=PTS-STARTPTS FFMPEG будет пытаться обрабатывать кадры в их "оригинальной" временной шкале, что может привести к:
- пропуску кадров;
- ошибкам синхронизации;
- "зависанию" потока.
setpts устраняет этот эффект, начиная отсчёт времени с нуля для каждого источника, что делает их временно совместимыми.
2. Влияние сетевой задержки и джиттера
Каждый RTSP-источник может идти по разному сетевому пути:
- одна камера — по Wi-Fi, другая — по кабелю;
- разные маршрутизаторы, разная загрузка каналов.
Это приводит к разной задержке (latency) и вариации задержки (jitter). FFMPEG использует входные буферы, чтобы компенсировать эти колебания, но:
- слишком большой буфер — увеличивает общую задержку;
- слишком маленький — вызывает обрывы и потери кадров.
В реальных системах можно использовать опции вроде:
-rtbufsize 100M— ограничение размера буфера приёма;-fflags nobuffer— уменьшение буферизации (но с риском потерь).
3. Нагрузка на CPU
Одновременная работа с четырьмя RTSP-потоками — это серьёзная нагрузка:
- 4 декодера — каждый поток нужно декодировать (H.264/H.265);
- 4 масштабирования — каждый кадр преобразуется в нужное разрешение;
- 1 композитинг — объединение в мозайку;
- 1 кодирование — финальный поток перекодируется.
Примерная нагрузка на CPU:
| Операция | Нагрузка (примерно) |
|---|---|
| Декодирование 1 потока | 10–25% CPU |
| Масштабирование | 5–10% CPU |
| Композитинг (xstack) | 5–15% CPU |
| Кодирование (libx264) | 20–40% CPU |
Итого: для 4 камер может потребоваться 60–100% одного ядра (в зависимости от разрешения, битрейта, настроек кодирования).
💡 Рекомендация: для масштабных систем (8+ камер) стоит рассмотреть:
- аппаратное декодирование (
h264_cuvid,h264_qsv);- использование GPU для масштабирования и композитинга;
- распределение нагрузки по нескольким серверам.
Практические сценарии использования
| Сценарий | Пример применения |
|---|---|
| Видеонаблюдение | Оператор видит 4 зоны одновременно на одном экране |
| Студийная съёмка | Режиссёр контролирует основную камеру, дублирующую, презентацию и гостя |
| Спортивная трансляция | Обзор с разных ракурсов: трибун, поле, судья, замены |
| Видеостена | 16 камер в сетке 4×4 на большой экран в ЦОДе или транспортном узле |
Возможные модификации команды
Мозаика 3×3 (9 камер)
-layout 0_0|640_0|1280_0|0_360|640_360|1280_360|0_720|640_720|1280_720
Финальное разрешение: 1920×1080.
Другие фильтры вместо xstack
tile=3x3— упрощённая сетка, но без гибкости позиционирования;hstack,vstack— горизонтальное или вертикальное объединение;overlay— для PIP (картинка в картинке), а не мозаики.
Итоги
Создание мозаики из нескольких RTSP-источников — типичная задача для FFMPEG, демонстрирующая его силу как универсального медиа-композитора. Однако за простотой команды скрывается сложная техническая реализация, включающая:
- синхронизацию временных шкал;
- компенсацию сетевой нестабильности;
- значительную вычислительную нагрузку.
Понимание этих аспектов позволяет:
- правильно проектировать видеосистемы;
- выбирать подходящее оборудование;
- настраивать FFMPEG для баланса между качеством, задержкой и производительностью.
Такой подход широко применяется в реальных инфраструктурах и является основой для более сложных композиций, которые мы рассмотрим в следующих разделах — включая PIP, аудиомикширование и динамические оверлеи.