В FFmpeg на самом деле довольно сложно сделать перекрестное затухание между двумя частями видеоконтента. Нет фильтра «перекрестного затухания», как для аудио.
Какой эффективный способ сделать это?
В FFmpeg на самом деле довольно сложно сделать перекрестное затухание между двумя частями видеоконтента. Нет фильтра «перекрестного затухания», как для аудио.
Какой эффективный способ сделать это?
В этом примере выполняется только видео, при условии, что оба видеоклипа имеют одинаковое разрешение, частоту кадров и т.д. Это создаст 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
Сначала мы разбиваем два потока на два, используя фильтр обрезки: содержимое и секцию перекрестного затухания. Затухание разбивается на раздел контента и затухания, а затухание - на раздел затухания и контент. Всего четыре раздела.
Обратите внимание, что, строго говоря, нам не нужно разбивать участки перекрестного затухания: мы МОЖЕМ просто указать время затухания и затухания для двух видеоклипов. Однако, делая это, мы:
overlay
фильтраКаждый из этих четырех разделов определяет: время начала (секунды), время окончания (секунды) и загадочный setpts=PTS-STARTPTS
, который, по сути, запускает каждый видеоклип с 0 секунд. Это будет жизненно важно при их перекомпоновке.
Обратите внимание, что спецификаторы s=0
являются избыточными, а фильтр setpts
для s=0
также избыточен. Тем не менее, оба указываются с избыточностью, чтобы позволить стартовое время изменить с 0, не нарушая комплекс фильтра. Кроме того, второй клип контента выполняется до конца, поэтому e=
part (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>
После этого вы можете позже рекомбинировать звук (за рамками этого вопроса).