Одна команда FFmpeg может уменьшить видео, наложить водяной знак и собрать два потока рядом. Это не три команды подряд, а граф фильтров. filter_complex выглядит страшно из-за квадратных скобок и точек с запятой, но логика там простая: потоки, узлы и связи.
Цепочка и граф
Фильтр-цепочка — это конвейер. Выход одного фильтра становится входом следующего, фильтры соединяются запятой:
scale=1280:-1,format=yuv420p,vflip
Сначала масштаб, затем пиксельный формат, затем вертикальный переворот.
Граф фильтров нужен, когда потоков несколько или данные надо разветвить и снова соединить. Цепочки разделяются точкой с запятой, а потоки помечаются метками в квадратных скобках:
[0:v]scale=640:480[a];[1:v]scale=640:480[b];[a][b]hstack
Практическое правило: одна последовательность фильтров — -vf; несколько входов или разветвление — -filter_complex. Строго говоря, -filter_complex шире: обычная цепочка -vf — просто его частный случай без ветвлений.
Метки — это виртуальные провода
Метка в квадратных скобках соединяет выход одного узла со входом другого:
Вход 0 ──[0:v]──> scale ──[a]──┐
├──> hstack ──> Выход
Вход 1 ──[1:v]──> scale ──[b]──┘
Та же команда:
ffmpeg -i left.mp4 -i right.mp4 -filter_complex \
"[0:v]scale=640:480[left];[1:v]scale=640:480[right];[left][right]hstack" \
out.mp4
Что здесь происходит:
[0:v]— видеопоток первого входа (0— номер-i,v— video; звук обозначаетсяa);scale=640:480[left]— обработанный поток получает меткуleft;[left][right]hstack— два потока подаются вhstackи складываются по горизонтали.
Выход без метки автоматически становится итоговым выходом графа. Поэтому после hstack ничего помечать не нужно.
-vf или -filter_complex
-vf | -filter_complex | |
|---|---|---|
| Входы | Один основной поток | Любое число потоков |
| Второй вход | Нет | Да, например [1:v] |
| Выход | Автоматически в выходной файл | Можно выбрать через -map |
| Звук | Не обрабатывается | Можно обрабатывать вместе с видео |
-vf — удобная сокращённая форма. Но в одной команде их лучше не смешивать, иначе легко получить два независимых конвейера.
Пример: масштаб и водяной знак
Поставим картинку в правый нижний угол и ограничим видео 720p:
ffmpeg -i input.mp4 -i logo.png -filter_complex \
"[1:v]scale=120:-1[wm];[0:v][wm]overlay=W-w-20:H-h-20,scale=-2:720" \
out.mp4
Разбор:
[1:v]scale=120:-1[wm]— логотип сжимается до 120 пикселей по ширине, высота считается автоматически.[0:v][wm]overlay=...— логотип накладывается на основное видео.WиH— размер основного кадра,wиh— размер логотипа. ЗначениеW-w-20:H-h-20оставляет отступ 20 пикселей.,scale=-2:720— видео уменьшается до 720 по высоте, а ширина выравнивается к чётному числу.
Полезные позиции для overlay: 0:0 — левый верх, (W-w)/2:(H-h)/2 — центр, 0:H-h — левый низ.
Пример: четыре потока в одной сетке
Каждый вход сжимается до половины ширины и высоты, затем раскладывается xstack:
ffmpeg -i a.mp4 -i b.mp4 -i c.mp4 -i d.mp4 -filter_complex \
"[0:v]scale=iw/2:ih/2[a];[1:v]scale=iw/2:ih/2[b];\
[2:v]scale=iw/2:ih/2[c];[3:v]scale=iw/2:ih/2[d];\
[a][b][c][d]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0" \
out.mp4
В layout w0 — ширина первого входа, h0 — его высота. Расположение задается относительными координатами меток.
Разветвить поток так же просто:
ffmpeg -i input.mp4 -filter_complex \
"[0:v]split=2[v1][v2];[v1]scale=320:-1[thumb];[v2]scale=1280:-2[main]" \
-map "[thumb]" thumb.jpg -map "[main]" main.mp4
split=2 делает две копии потока, дальше каждая идёт своей цепочкой, а -map решает, что попадёт в какой файл.
Как дебажить
Длинный граф почти всегда падает с первого раза. Несколько привычек, которые экономят время:
- Проверяйте по частям. Сначала запустите один фильтр, потом добавляйте следующий.
- Включайте
-v error. FFmpeg и без того много говорит; ошибки сразу виднее. - Читайте метки в ошибке.
Invalid argumentи метка после него обычно показывают, где порвалась связь. - Сначала выравнивайте разрешение.
hstackиvstackтребуют одинаковых размеров, а несовпадающий пиксельный формат уoverlayможет тихо убить скорость. Перед соединением приводите потоки кscaleиformat=yuv420p.
Итог
Фильтр-граф — это поток данных: фильтр — узел, метка — провод. Когда понятно, как соединяются [a], [b] и [0:v], остаётся заглянуть в документацию по конкретным параметрам.
В инструменте для водяных знаков, конвертере видео в GIF и лаборатории FFmpeg-команд это можно проверить прямо в браузере.
FAQ
В: Имеет ли значение порядок фильтров? О: Да, и для качества, и для размера. Обычно лучше сначала уменьшить видео, но фильтры шумоподавления чаще ставят до масштабирования.
В: Чем -1 отличается от -2 в scale?
О: -1 просто сохраняет пропорции, -2 дополнительно выравнивает размер к чётному числу. Для H.264 и H.265 обычно нужен -2.
В: Почему overlay работает очень медленно?
О: Часто у видео и картинки разные пиксельные форматы, и FFmpeg конвертирует их на каждом кадре. Явный format=yuv420p у обоих потоков обычно помогает.