Цепочка фильтров filtergraph и её влияние на задержку

В предыдущих частях лекции мы рассмотрели, как FFMPEG может выступать в роли медиашлюза, принимая поток по одному протоколу и отправляя его по другому — с возможностью перекодирования, ремультиплексации и распределения на несколько выходов. Однако, помимо кодирования и передачи, FFMPEG обладает мощными возможностями по обработке видео и аудио в реальном времени с помощью так называемых фильтров. Эти фильтры позволяют изменять изображение, накладывать графику, комбинировать источники и улучшать качество сигнала. Но за эту гибкость приходится платить — временем и ресурсами.
В этом разделе мы подробно разберём, что такое filtergraph, как он устроен, какие ресурсы потребляет и как влияет на задержку в системах потокового видео.
Что такое filtergraph?
Filtergraph — это граф обработки медиаданных в FFMPEG, состоящий из одного или нескольких фильтров, соединённых между собой. Он описывает, как видео- и аудиопотоки преобразуются между декодированием и кодированием.
Фильтры могут выполнять самые разные задачи:
- изменение размера изображения (
scale); - наложение текста (
drawtext); - наложение изображений (
overlay); - устранение шумов (
hqdn3d); - деинтерлейсинг (
yadif); - коррекция цвета (
eq); - синхронизация нескольких источников (
setpts,adelay).
FFMPEG поддерживает два типа filtergraph:
- Простые (simple) — обрабатывают один поток (например,
scale=1280:720). - Сложные (complex) — работают с несколькими входами и выходами, позволяя комбинировать потоки (например, картинка в картинке, мозайка, микширование аудио).
🔍 Пример простого filtergraph:
-vf "scale=1280:720,fps=30"— масштабирует видео и изменяет частоту кадров.Пример сложного filtergraph:
-filter_complex "[0:v][1:v]overlay=10:10[out]"— накладывает второй видеопоток поверх первого.
Как фильтры влияют на задержку?
Каждый фильтр в filtergraph может добавлять собственные буферы, необходимые для корректной обработки. Эти буферы накапливают кадры или аудиосэмплы, чтобы фильтр мог «увидеть» больше данных и принять решение. Это приводит к увеличению задержки (latency) — времени между поступлением кадра на вход и его появлением на выходе.
Рассмотрим, как это работает на примерах.
1. Фильтр масштабирования (scale)
Даже такой, казалось бы, простой фильтр, как scale, может вносить задержку. При изменении размера изображения FFMPEG должен обработать каждый пиксель, а при использовании некоторых алгоритмов интерполяции (например, lanczos) — анализировать окрестности пикселей. Это требует временного хранения нескольких строк кадра в буфере.
📌 Пример:
При масштабировании с 1920×1080 до 640×360 с фильтромlanczosFFMPEG может задерживать 1–3 кадра, чтобы корректно рассчитать новые пиксели.
2. Фильтр деинтерлейсинга (yadif)
Интерлейсированные видеопотоки (например, с камер старых стандартов) содержат чересстрочные кадры. Фильтр yadif (Yet Another De-Interlacing Filter) восстанавливает полные кадры, анализируя как текущее, так и предыдущее/следующее поле. Для этого ему нужен доступ к нескольким полям, что требует буферизации.
📌 Последствие:
Фильтрyadifможет добавлять задержку в 2–4 кадра, так как не может выдать первый полный кадр, пока не получит как минимум два поля.
3. Фильтр шумоподавления (hqdn3d)
Фильтры подавления шума, такие как hqdn3d, работают, анализируя изменения не только в пространстве (между пикселями), но и во времени (между кадрами). Это означает, что фильтр накапливает несколько кадров, чтобы отличить шум от реального движения.
📌 Эффект:
Даже при небольшой настройкеhqdn3dможет вносить задержку в 5–10 кадров, особенно при высоком разрешении.
Сложные цепочки: мультивью, оверлеи, титры
Когда фильтры объединяются в сложные графы, задержка накапливается. Рассмотрим типичные сценарии.
Пример 1: Наложение логотипа (overlay)
ffmpeg -i rtsp://cam -i logo.png -filter_complex "[0:v][1:v]overlay=10:10" -f flv rtmp://server/stream
Здесь:
- Видеопоток с камеры декодируется.
- PNG-логотип декодируется и постоянно накладывается.
- Каждый кадр проходит через фильтр
overlay.
Хотя overlay сам по себе быстрый, он всё равно требует:
- синхронизации временных меток (PTS) двух потоков;
- буферизации кадра с логотипом;
- дополнительной обработки при прозрачности.
⚠️ Итог: даже простое наложение изображения добавляет 1–2 кадра задержки.
::: info Интересный факт: если вы накладываете файл поверх видео (например, PNG), то этот файл считывается при формировании каждого выходного кадра. А значит, если подменять файл достаточно часто, то можно получить анимацию.
И это не обязательно маленький логотип в углу кадра. PNG может совпадать с размером экрана, просто быть по умолчанию полностью прозрачным. Дальше в нужные моменты подкладываются красивые последовательности, где вылетают плашки с титрами или другое оформление.
Это "колхозный" метод, но вполне рабочий. Главное -- обеспечить условия для быстрого копирования файлов, иначе анимация будет дергаться. Все это требует ресурсов. Увлекаться этим не стоит, но заменить какую-нибудь громоздкую титровальную систему в небольшом сетапе для стриминга так можно.
:::
Пример 2: Мозаика из 4 камер (2×2)
ffmpeg -i cam1 -i cam2 -i cam3 -i cam4 -filter_complex \
"[0:v]scale=640:360[1v]; [1:v]scale=640:360[2v]; [2:v]scale=640:360[3v]; [3:v]scale=640:360[4v]; \
[1v][2v][3v][4v]xstack=inputs=4:layout=..." -f flv rtmp://server/mosaic
Здесь:
- 4 видеопотока декодируются параллельно;
- каждый масштабируется;
- все синхронизируются по времени;
- объединяются в одну картинку.
⚠️ Задержка:
- Каждый
scale— 1–2 кадра;xstack— 1–3 кадра на синхронизацию;- Разная задержка от камер (из-за сети) — до 5 кадров;
Суммарно: 5–10 кадров (200–400 мс при 25 fps).
Пример 3: Динамические титры (drawtext)
ffmpeg -i rtsp://cam -vf "drawtext=text='%{localtime}':x=10:y=10:box=1" ...
Фильтр drawtext генерирует текст на каждом кадре. Это требует:
- вызова системной функции получения времени;
- рендеринга шрифта;
- наложения текста на изображение.
🔧 Нюанс:
При использовании переменных (например,%{localtime}), FFMPEG должен пересчитывать текст для каждого кадра, что увеличивает нагрузку на CPU и может замедлять обработку.
Баланс между качеством и задержкой
Инженер, проектирующий систему потокового видео, всегда стоит перед выбором: что важнее — визуальное качество и функциональность или минимальная задержка?
| Сценарий | Приоритет | Рекомендации |
|---|---|---|
| Видеонаблюдение (реагирование в реальном времени) | Минимальная задержка | Отказаться от фильтров, использовать -c copy, перенести титры в камеру или клиент |
| Онлайн-вебинар с докладчиком | Средняя задержка, высокая наглядность | Допустимы оверлеи, титры, PIP, но избегать сложных фильтров (шумоподавление, масштабирование с lanczos) |
| Массовая трансляция (YouTube, Twitch) | Стабильность, качество | Можно использовать сложные filtergraph, так как задержка 5–10 секунд допустима |
| Видеосвязь, интерактивный контроль | Очень низкая задержка (< 200 мс) | Избегать FFMPEG в цепочке, использовать GStreamer или WebRTC-шлюзы |
Где размещать обработку: стратегия оптимизации
Не всегда обработку нужно выполнять в FFMPEG. Иногда выгоднее перенести часть задач ближе к источнику или ближе к получателю.
Варианты размещения обработки:
| Этап | Возможность обработки | Плюсы | Минусы |
|---|---|---|---|
| Источник (камера) | Встроенная поддержка титров, водяных знаков, масштабирования | Не нагружает сервер, минимальная задержка | Ограниченный функционал, зависит от модели камеры |
| FFMPEG (сервер) | Полный контроль: фильтры, композитинг, микширование | Гибкость, поддержка сложных сценариев | Высокая нагрузка на CPU, увеличение задержки |
| Клиент (плеер) | Отображение титров, оверлеев в браузере или приложении | Никакой задержки на сервере, интерактивность | Требует поддержки на стороне клиента, не подходит для архивации |
💡 Рекомендация:
Если титры нужны только для просмотра, но не для записи — лучше показывать их на стороне клиента.
Если титры — часть архива или трансляции — обрабатывать в FFMPEG, но упрощать filtergraph.
Итоги: «красивые эффекты» стоят времени и CPU
- Каждый фильтр в filtergraph может добавлять задержку, так как использует внутренние буферы для корректной работы.
- Сложные filtergraph (мозайка, PIP, шумоподавление) накапливают задержку и требуют значительных вычислительных ресурсов.
- Наложение текста, логотипов, титров требует перекодирования, даже если в остальном поток можно было бы копировать (
-c copy). - Выбор места обработки (камера, сервер, клиент) — ключевой инженерный компромисс между задержкой, качеством и нагрузкой.