Перейти к основному содержимому

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

06-03-04

В предыдущих частях лекции мы рассмотрели, как 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 с фильтром lanczos FFMPEG может задерживать 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).
  • Выбор места обработки (камера, сервер, клиент) — ключевой инженерный компромисс между задержкой, качеством и нагрузкой.