Какой эффективный способ сделать видео кроссфейд с FFmpeg?

11

В FFmpeg довольно сложно сделать перекрестное затухание между двумя частями видеоконтента. Нет фильтра «перекрестного затухания», как для аудио.

Какой эффективный способ сделать это?

Марк Геролиматос
источник
Хороший вопрос с ответом!
JakeGould
Этот ответ должен получить ОЧЕНЬ больше голосов ... Марк, я бы так любил тебя всегда, если бы ты тоже добавил кроссфейдинг для звука ...
Merc
Как только я выясню, как, я добавлю это. Я думаю, что кроссфейд аудио очень прост, хотя, поверьте, есть простой фильтр для него.
Марк Геролиматос
Я просто добавил [0:a][1:a] acrossfade=d=1 [audio]в фильтр, а затем -map "[audio]" в команду, и это сработало. Если хотите, пройдите тест и обновите ответ!
Merc

Ответы:

17

TL; DR версия:

В этом примере выполняется только видео, при условии, что оба видеоклипа имеют одинаковое разрешение, частоту кадров и т. Д. Это создаст 1-секундное замирание между fadeoutclip и fadeinclip. Предположим, что fadeoutclip длится 10 секунд. Обратите внимание, что это отформатировано для ясности: это действительно одна строка кода.

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an \
-filter_complex "\
    [0:v]trim=start=0:end=9,setpts=PTS-STARTPTS[firstclip]; \
    [1:v]trim=start=1,setpts=PTS-STARTPTS[secondclip]; \
    [0:v]trim=start=9:end=10,setpts=PTS-STARTPTS[fadeoutsrc]; \
    [1:v]trim=start=0:end=1,setpts=PTS-STARTPTS[fadeinsrc]; \
    [fadeinsrc]format=pix_fmts=yuva420p, \
                fade=t=in:st=0:d=1:alpha=1[fadein]; \
    [fadeoutsrc]format=pix_fmts=yuva420p, \
                fade=t=out:st=0:d=1:alpha=1[fadeout]; \
    [fadein]fifo[fadeinfifo]; \
    [fadeout]fifo[fadeoutfifo]; \
    [fadeoutfifo][fadeinfifo]overlay[crossfade]; \
    [firstclip][crossfade][secondclip]concat=n=3[output] \
    " \
-map "[output]" <add in encoding part here>

Полная версия:

Вот объяснение того, что это было все:

Спецификация ввода ... очевидно

ffmpeg -i fadeoutclip.mp4 -i fadeinclip.mp4 -an

Создание filter_complex: при условии, что вы уже понимаете комплексы фильтров:

-filter_complex

Сначала мы разбиваем два потока на две части, используя фильтр обрезки : содержимое и секцию перекрестного затухания. Затухание разбивается на раздел контента и затухания, а затухание - на раздел затухания и контент. Всего четыре раздела.

Обратите внимание, что, строго говоря, нам не нужно разбивать участки перекрестного затухания: мы МОЖЕМ просто указать время затухания и затухания для двух видеоклипов. Однако, делая это, мы:

  • Следуйте методологии, обычно используемой графическими редакторами GUI
  • Избегайте разочаровывающей сложности использования overlayфильтра
  • Убедитесь, что решение максимально общее (т. Е. Повторно используемый код)
  • Позвольте нам предварительно обработать и обработать раздел кроссфейда по мере необходимости (здесь это не сделано)

В каждом из этих четырех разделов указываются: время начала (секунды), время окончания (секунды) и загадочный setpts=PTS-STARTPTSфильтр , который, по сути, запускает каждый видеоклип с 0 секунд. Это будет жизненно важно при их повторном создании.

Обратите внимание, что s=0спецификаторы являются избыточными, а setptsфильтр для s=0них также избыточен. Тем не менее, оба указываются с избыточностью, чтобы позволить изменение времени начала с 0, не нарушая комплекс фильтра. Кроме того, второй клип контента выполняется до конца, поэтому e=часть (end =) не указана.

    [0:v]trim=s=0:e=9,setpts=PTS-STARTPTS[firstclip];
    [1:v]trim=s=1,setpts=PTS-STARTPTS[secondclip];
    [0:v]trim=s=9:e=10,setpts=PTS-STARTPTS[fadeoutsrc];
    [1:v]trim=s=0:e=1,setpts=PTS-STARTPTS[fadeinsrc];

Далее мы указываем постепенное увеличение и уменьшение. Сначала мы добавляем альфа-канал (прозрачность) в обе части постепенного изменения, указав формат пикселяyuva420p . Вы можете использовать любой формат, который обеспечивает альфа-канал.

Далее в этом подкомплексе фильтра мы указываем один для постепенного исчезновения, а другой для постепенного исчезновения. Это alpha=1означает, что само видео не будет затемняться, только «прозрачность» будет «исчезать». stозначает начало, dзначит продолжительность.

    [fadeinsrc]format=pix_fmts=yuva420p,      
                fade=t=in:st=0:d=1:alpha=1[fadein];
    [fadeoutsrc]format=pix_fmts=yuva420p,
                fade=t=out:st=0:d=1:alpha=1[fadeout];

Что это ?: В fifoфильтр гарантирует , что есть буфер пространства , доступного в фильтре комплекса. Удивительно, но это не по умолчанию. Если вы этого не сделаете, кроссфейд может потерпеть неудачу, если выходные данные вышеприведенного каскада превысят фильтр наложения ниже. Да, я знаю, о чем ты сейчас думаешь. Это действительно ошибка FFMPEG .

    [fadein]fifo[fadeinfifo];
    [fadeout]fifo[fadeoutfifo];

Теперь наложите две секции затухания: убедившись, что две секции перекрестного затухания имеют одинаковый размер, нам не нужно беспокоиться о довольно неприятных опциях, которые принимает фильтр наложения (и поэтому мы их здесь игнорируем):

    [fadeoutfifo][fadeinfifo]overlay[crossfade];

Наконец, мы выстраиваем наши три сегмента, используя фильтр concat .

    [firstclip][crossfade][secondclip]concat=n=3[output]

А теперь сопоставьте выходную панель как источник видео.

НЕ ЗАБУДЬТЕ установить формат пикселя в ТО, ЧТО ВЫ НОРМАЛЬНО ИСПОЛЬЗУЕТЕ (обычно yuv420p), поскольку секция кроссфейдера установит его yuv420на выходном канале! (поскольку мы не указали это, вы можете использовать оверлейные аргументы) Конечно, если вы хотите yuv420, то все в порядке :-)

-map "[output]" <add your normal encoding part here>

Затем вы можете потом объединить аудио (за рамками этого Q & A)

Марк Геролиматос
источник
1
В последнем ffmpeg это должно быть trim=start=0:end=9(а не trim=st=0:e=9,..
Merc
А если серьезно, это должен быть лучший ответ о FFMPEG, который я когда-либо видел, и самое ясное объяснение ffmpeg.
Merc
Человек, это собирается пойти в мою голову :-) Спасибо за опоры !!!!
Марк Gerolimatos
Без проблем. Пожалуйста, обновите ответ, особенно с помощью = trim = start = 0, так как сейчас он не работает с последней версией ffmpeg
Merc
Последняя версия ffmpeg дает мне эту ошибку: Filter setpts has an unconnected outputдля скрипта. Я уже изменил параметры обрезки, чтобы начать и закончить.