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

Напоминание: базовая модель работы FFMPEG

06-01-02

В этом разделе мы кратко вспомним внутреннюю структуру обработки медиаданных в FFMPEG — не с позиции перекодирования файлов, как это было в курсе «Компьютерная графика», а с акцентом на сетевые видеосистемы. Эта модель — фундамент для понимания, как FFMPEG работает с потоковым видео, где возникает задержка и почему обработка сетевых источников отличается от работы с локальными файлами.


Общая схема обработки медиапотока

В основе FFMPEG лежит конвейерная (пайплайновая) архитектура, в которой данные последовательно проходят несколько этапов обработки. Упрощённо её можно представить так:

input(s) → демультиплексор → декодеры → фильтры → кодеры → мультиплексор → output(s)

Рассмотрим каждый этап подробно, с акцентом на сетевое применение.


1. Вход (input)

На этом этапе FFMPEG получает исходный медиапоток. Важно понимать, что для FFMPEG не имеет принципиального значения, откуда приходят данные — с диска или из сети.

  • Файловый ввод: input.mp4, video.mkv и т.п.
  • Сетевой ввод: rtsp://cam1/stream, rtmp://server/live/stream, srt://192.168.1.10:1234, udp://239.1.1.1:1234

💡 Ключевая мысль: с точки зрения формата и структуры данных — это одно и то же. FFMPEG видит поток байт, из которого нужно извлечь медиаданные. Различается только способ получения этих байт: через файловую систему или через сетевой сокет.

Например, команда:

ffmpeg -i rtsp://192.168.1.10:554/stream -c copy output.mp4

работает так же, как:

ffmpeg -i local_video.mp4 -c copy output.mp4

— с той лишь разницей, что в первом случае данные приходят по сети, а во втором — с диска.


2. Демультиплексор (Demuxer)

Демультиплексор отвечает за разделение потока на отдельные компоненты: видео, аудио, субтитры и т.д. Он анализирует контейнер (формат файла или потока) — например, MP4, MKV, FLV, MPEG-TS, RTSP/RTP.

  • Для rtsp://... демультиплексор распознаёт RTP-пакеты, извлекает NAL-юниты H.264 и временные метки.
  • Для input.mp4 он читает атомы moov, mdat и извлекает треки.

⚠️ Важно: демультиплексору нужно достаточно данных, чтобы понять структуру потока. В случае с сетевым входом это может потребовать буферизации первых пакетов. Это уже источник начальной задержки.


3. Декодеры (Decoders)

На этом этапе сжатые данные (например, H.264, AAC) преобразуются в «сырой» формат, пригодный для обработки:

  • Видео: из H.264 → в YUV (например, yuv420p)
  • Аудио: из AAC → в PCM (например, s16le)

Каждый поток (видео, аудио) проходит через свой декодер. Если в команде указано -c copy, этот этап пропускается — данные передаются без декодирования.

🔍 Пример:
При работе с IP-камерой, которая передаёт H.264 в контейнере RTSP/RTP, FFMPEG может либо:

  • декодировать H.264 → YUV → (фильтры) → (перекодировать) → H.264,
  • или пропустить декодирование, если используется -c copy.

4. Фильтры (Filters)

Это этап обработки «сырого» медиа. FFMPEG поддерживает богатую систему фильтров (filtergraph), включая:

  • Масштабирование (scale=1280:720)
  • Наложение картинки (overlay)
  • Добавление текста (drawtext)
  • Деинтерлейсинг, шумоподавление, поворот и т.д.

⚠️ Каждый фильтр — потенциальный источник задержки, потому что:

  • Ему может потребоваться накопить несколько кадров (например, для шумоподавления или стабилизации).
  • Фильтры работают синхронно: обработка одного кадра блокирует следующий, пока не завершится.

💡 Пример:
Фильтр hqdn3d (высококачественное шумоподавление) использует буферы для анализа соседних кадров. Это добавляет задержку в 2–3 кадра.


5. Кодеры (Encoders)

На этом этапе «сырое» видео или аудио снова сжимается — уже в нужный формат на выходе.

  • Например: YUV → H.264 с помощью libx264
  • Или: PCM → AAC с помощью libfdk_aac

Кодирование — один из самых ресурсоёмких и буфероёмких этапов. Особенно если используются сложные настройки: длинный GOP, look-ahead, B-кадры.

🔍 Пример:
При трансляции в RTMP часто используется:

-c:v libx264 -preset veryfast -tune zerolatency

Эти параметры уменьшают задержку, но увеличивают нагрузку на CPU.


6. Мультиплексор (Muxer)

Мультиплексор «упаковывает» закодированные потоки в выходной контейнер (формат). Например:

  • H.264 + AAC → FLV (для RTMP)
  • H.264 + AAC → MPEG-TS (для SRT или UDP)
  • H.264 + AAC → MP4/MKV (для записи)

⚠️ Мультиплексор также буферизует данные, особенно если:

  • Нужно дождаться ключевого кадра (I-frame) для начала записи.
  • Формат требует метаданных в начале файла (например, moov в MP4).

7. Выход (output)

Финальный этап — отправка данных:

  • В файл: output.mp4
  • В сеть: rtmp://..., srt://..., udp://...

Как и на входе, сеть требует буферизации:

  • Для TCP — буферы сокета
  • Для UDP/RTP — буферы джиттера (jitter buffer)
  • Для SRT — встроенный механизм компенсации потерь и задержки

Где возникают буферы и задержка?

Задержка (латентность) в FFMPEG — это сумма задержек на каждом этапе. Ниже приведена таблица с основными источниками:

ЭтапИсточник задержкиПримеры
Вход (input)Сетевой буфер, ожидание пакетов-rtbufsize, TCP receive buffer
ДемультиплексорОжидание I-кадра, анализ форматаПервая пауза при запуске RTSP
ДекодерВнутренние буферы декодера (B-кадры)H.264 с B-кадрами → +2–3 кадра
ФильтрыНакопление кадров для обработкиhqdn3d, deinterlace, overlay
КодерLook-ahead, GOP, VBV-буфер-g 60, -bf 2, -bufsize 2M
МультиплексорБуферизация перед записью/отправкойFLV: ждёт первый I-кадр
ВыходСетевой буфер, jitter bufferSRT latency=120, UDP-джиттер

📌 Пример:
При приёме RTSP с IP-камеры и отправке в RTMP с транскодированием и фильтрами:

  • Вход: 50–100 мс (TCP-джиттер)
  • Демультиплексор: 50 мс (ожидание I-кадра)
  • Декодер: 33 мс (один B-кадр при 30 fps)
  • Фильтр масштабирования: 33 мс
  • Кодер: 100 мс (look-ahead + GOP)
  • Мультиплексор: 50 мс
  • Выход: 50 мс (RTMP-буфер)

Итого: ~366 мс задержки — без учёта сети и клиентского плеера.


Почему «живой» поток отличается от локального файла?

ХарактеристикаЛокальный файлСетевой поток
Доступ к даннымПолный, мгновенныйПостепенный, с задержкой
СтабильностьНет потерь пакетовВозможны потери, джиттер
СинхронизацияТочная (все кадры на месте)Требуется выравнивание (PTS/DTS)
БуферизацияМинимальнаяОбязательная (для стабильности)
ПеремоткаВозможнаНедоступна (в режиме реального времени)
ЗадержкаПрактически нулеваяСуммарная, накапливается на каждом этапе

💡 Пример:
При запуске ffplay rtsp://cam/stream вы можете заметить, что:

  • Первые 1–2 секунды — чёрный экран (демультиплексор ждёт I-кадр),
  • Затем изображение «подпрыгивает» — это выравниваются временные метки,
  • После этого идёт плавное воспроизведение, но с задержкой в 500-1000 мс, часто больше.

::: warn FFMPEG (и FFPLAY) при воспроизведении RTSP-потоков делает очень заметную задержку. Секунда -- это ещё хороший случай, может быть и две. Действительно быстрое отображение RTSP получается у GStreamer, с которым мы познакомимся в следующей лекции.

:::


Практическое значение схемы

Эта модель не просто теория — она нужна для настройки и оптимизации:

  • Чтобы уменьшить задержку, вы должны понимать, где она возникает.
  • Чтобы выбрать режим работы (-c copy vs транскодирование), нужно знать, что происходит на каждом этапе.
  • Чтобы диагностировать проблемы, вы смотрите логи и определяете, на каком этапе происходит сбой.

🔧 Совет:
Всегда начинайте с -c copy, если возможно. Это исключает декодирование и кодирование — два самых тяжёлых и буфероёмких этапа.


Итог

FFMPEG — это универсальный конвейер обработки медиаданных, где:

  • Файловый и сетевой ввод с точки зрения формата — эквивалентны.
  • Задержка — это сумма буферов на каждом этапе: вход, демультиплексор, декодер, фильтры, кодер, мультиплексор, выход.
  • Работа с «живым» потоком требует буферизации, синхронизации и устойчивости к потерям — в отличие от локальных файлов.

🎯 Важно: Эта схема будет использоваться далее при разборе протоколов (RTSP, RTMP, SRT), транскодирования, мультивью и настройки низкой задержки. Понимание пайплайна — ключ к эффективной работе с FFMPEG в сетевых видеосистемах.