FFmpeg | Граф фильтров (filter_complex)
от aNNiMON
В этой статье я подробно расскажу как применять несколько фильтров подряд в -filter_complex, тем самым создавая цепочку или очень сложный граф.
Содержание:
- Цепочка и граф фильтров
- Фильтр split
- Когда использовать -vf, а когда -filter_complex
⚠️ Для удобства восприятия команд, я буду переносить некоторые части на новую строку. Чтобы командная строка Windows понимала, что это продолжение одной команды, перед переносом ставится символ ^
В MacOS и Linux для той же цели используется символ \
В дальнейшем я буду использовать вариант для Windows. Если у вас другая операционная система, перед применением команды необходимо заменить символ ^ на \
Цепочка фильтров (filterchain) — последовательность фильтров, перечисленных через запятую ,. Например:
Граф фильтров (filtergraph) — последовательность из фильтров или цепочек фильтров, разделённых точкой с запятой ;
В этом случае получается граф:
Давайте разбираться. В этом примере мы имеем дело с тремя входными файлами:
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 (для аудиопотоков).
В этот раз получается тот же результат, только теперь вместо второго логотипа logo2.png используется первый логотип logo.png, который дублируется на два потока.
Когда использовать -vf, а когда -filter_complex-vf используется в случаях, когда в графе есть только один вход и только один выход, а -filter_complex — когда имеем один или несколько входов и один или несколько выходов.
Вот пример отзеркаливания — обрезки левой половины видео, последующего отражения и наложения в правую часть поверх оригинального видео:
Поскольку здесь один вход и один выход, можно использовать -vf.
Следующая статья →Содержание:
- Цепочка и граф фильтров
- Фильтр split
- Когда использовать -vf, а когда -filter_complex
⚠️ Для удобства восприятия команд, я буду переносить некоторые части на новую строку. Чтобы командная строка Windows понимала, что это продолжение одной команды, перед переносом ставится символ ^
- ffmpeg ^
- -i input.mp4 ^
- result.mp4
- ffmpeg \
- -i input.mp4 \
- result.mp4
Цепочка фильтров (filterchain) — последовательность фильтров, перечисленных через запятую ,. Например:
- -vf hflip,vflip
- -vf rotate=PI/2,crop=600:600,hflip
- ffmpeg -i input.mp4 -i logo.png -i logo2.png ^
- -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" ^
- result.mp4
Давайте разбираться. В этом примере мы имеем дело с тремя входными файлами:
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 (для аудиопотоков).
- ffmpeg -i input.mp4 -i logo.png ^
- -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" ^
- result.mp4
В этот раз получается тот же результат, только теперь вместо второго логотипа logo2.png используется первый логотип logo.png, который дублируется на два потока.
Когда использовать -vf, а когда -filter_complex-vf используется в случаях, когда в графе есть только один вход и только один выход, а -filter_complex — когда имеем один или несколько входов и один или несколько выходов.
Вот пример отзеркаливания — обрезки левой половины видео, последующего отражения и наложения в правую часть поверх оригинального видео:
- ffmpeg -i input.mp4 ^
- -vf split[s1][s2];[s2]crop=iw/2:ih:0:0,hflip[s3];[s1][s3]overlay=W/2:0 ^
- result.mp4
Размещение видео бок о бок или стеной