FFmpeg | Граф фильтров (filter_complex)

от
FFmpeg    filter graph, граф фильтров, filter_complex

В этой статье я подробно расскажу как применять несколько фильтров подряд в -filter_complex, тем самым создавая цепочку или очень сложный граф.

Содержание:
  - Цепочка и граф фильтров
  - Фильтр split
  - Когда использовать -vf, а когда -filter_complex

⚠️ Для удобства восприятия команд, я буду переносить некоторые части на новую строку. Чтобы командная строка Windows понимала, что это продолжение одной команды, перед переносом ставится символ ^
  1. ffmpeg ^
  2.   -i input.mp4 ^
  3.   result.mp4
В MacOS и Linux для той же цели используется символ \
  1. ffmpeg \
  2.   -i input.mp4 \
  3.   result.mp4
В дальнейшем я буду использовать вариант для Windows. Если у вас другая операционная система, перед применением команды необходимо заменить символ ^ на \

Цепочка фильтров (filterchain) — последовательность фильтров, перечисленных через запятую ,. Например:
  1. -vf hflip,vflip
  2. -vf rotate=PI/2,crop=600:600,hflip
Граф фильтров (filtergraph) — последовательность из фильтров или цепочек фильтров, разделённых точкой с запятой ;
  1. ffmpeg -i input.mp4 -i logo.png -i logo2.png ^
  2.        -filter_complex "[1:v]rotate=PI,hflip[logo];[0:v][logo]overlay=10:10[a];[a][2:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10" ^
  3.        result.mp4
В этом случае получается граф:
shot-20210328T200249.png

Давайте разбираться. В этом примере мы имеем дело с тремя входными файлами:
  input.mp4, logo.png и logo2.png
Каждый входной файл или поток в ffmpeg пронумерован. Самому первому перечисленному присваивается индекс 0, второму — 1 и так далее по порядку.
То есть input.mp4 будет иметь индекс 0, logo.png — индекс 1, logo2.png — индекс 2.

Чтобы указать конкретный входной файл, используются форматы:
[индекс] — для указания всего файла ([1])
[индекс:v] — для указания видеопотока из этого файла ([1:v])
[индекс:a] — для указания аудиопотока из этого файла ([1:a])
Последние два формата используются для случаев, когда нужно указать конкретный поток в файле. Например, видео обычно состоит из видеопотока и аудиопотока. Аудиофайлы имеют только аудиопоток (но могут ещё иметь и видеопоток с картинкой обложки альбома). Изображения имеют только видеопоток.

Большинство фильтров принимают на вход один видеопоток и отдают на выходе один видеопоток. Записывается это так:
-filter_complex "[1:v]hflip[logo]"
Сначала идёт входной поток, потом название фильтра и его параметры (или цепочки фильтров), а в конце название выходного файла.
В данном случае, второй входной файл будет отражён по-горизонтали, а результат будет помещён в поток с названием logo.

Добавим ещё один фильтр:
-filter_complex "[1:v]rotate=PI,hflip[logo]"
Теперь второй входной файл будет повёрнут на 180° и отражён по-горизонтали.

Есть фильтры, которые принимают два и более потоков, а на выходе производят один поток. К таким относится фильтр overlay, который принимает два видеопотока.
-filter_complex "[1:v]rotate=PI,hflip[logo];[0:v][logo]overlay=10:10[a]"
Фильтр берёт первый входной файл (поток [0:v]) и повёрнутый логотип (поток [logo]), размещает логотип в координатах 10:10 (левый верхний угол), а результат отправляет в именованный поток [a].

Наконец, заключительный фильтр в графе накладывает третий файл (поток [2:v]) на получившийся ранее результат (поток [a]) в правый нижний угол:
-filter_complex "[1:v]rotate=PI,hflip[logo];[0:v][logo]overlay=10:10[a];[a][2:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10"
Так как это последний фильтр и именно его результат нам нужен в итоге, название выходному потоку мы уже не даём.

Таким образом можно выстраивать очень сложные вариации фильтров.


Фильтр splitНо есть и фильтры, которые принимают один поток, а на выход отправляют два. Это фильтр split (для видео потоков) и asplit (для аудиопотоков).
  1. ffmpeg -i input.mp4 -i logo.png ^
  2.        -filter_complex "[1:v]split[logo1a][logo2];[logo1a]rotate=PI,hflip[logo1b];[0:v][logo1b]overlay=10:10[a];[a][logo2]overlay=main_w-overlay_w-10:main_h-overlay_h-10" ^
  3.        result.mp4
shot-20210329T144452.png
В этот раз получается тот же результат, только теперь вместо второго логотипа logo2.png используется первый логотип logo.png, который дублируется на два потока.


Когда использовать -vf, а когда -filter_complex-vf используется в случаях, когда в графе есть только один вход и только один выход, а -filter_complex — когда имеем один или несколько входов и один или несколько выходов.

Вот пример отзеркаливания — обрезки левой половины видео, последующего отражения и наложения в правую часть поверх оригинального видео:
  1. ffmpeg -i input.mp4 ^
  2.    -vf split[s1][s2];[s2]crop=iw/2:ih:0:0,hflip[s3];[s1][s3]overlay=W/2:0 ^
  3.    result.mp4
Поскольку здесь один вход и один выход, можно использовать -vf.

  • +2
  • views 6936