Недавно у меня возникла следующая проблема:
Я хотел, используя ffmpeg, объединить несколько видео (со звуком), добавив между ними черные клипы (с нулевым звуком) и, наконец, исчезнуть видео из этих черных клипов ( fade-in ) и этих черных клипов ( fade-out ) .
Схематически, например, с 2 видео:
black (1s) --> part_1 (60s) --> black (3s) --> part_2 (120s) --> black (1s)
^ ^ ^ ^
(2s-fade-in) (2s-fade-out) (2s-fade-in) (2s-fade-out)
Я искал однострочное решение (чтобы избежать повторного кодирования исходных видео более одного раза), но нашел только документацию или справку по каждой части проблемы.
Разобравшись, захотел задокументировать свое решение для тех, кто после меня наткнется на подобную проблему :)
Итак, вот что я придумал.
ffmpeg -f lavfi -i "color=black:s=1920x1080:r=30" \
-f lavfi -i "anullsrc=r=48000:cl=stereo" \
-c:v libx264 -c:a aac -t 3 empty_3s.mp4
Используйте фильтры lavfi для создания пустого клипа. Конечно, измените параметры в соответствии с вашими видео и тем, чего вы хотите достичь. Особенно:
s
(размер) должен соответствовать размеру видео, которые вы хотите объединить.r
(частота кадров) также должна соответствовать вашим видео (особенно если вам нужна постоянная частота кадров)r
(частота дискретизации) должна совпадать с частотой звуковых дорожек из видео, которые вы хотите объединить.cl
(макет канала) также должен соответствовать звуку из ваших видео.Выходные параметры (например, кодеки) должны соответствовать параметрам ваших видео. Используйте -t
для установки длины (в секундах) пустого клипа.
ffmpeg -i empty_1s.mp4 -i part_1.mp4 -i empty_3s.mp4 -i part_2.mp4 -i empty_1s.mp4 \
-filter_complex \
"[1:v] fade=t=in:st=0:d=2, fade=t=out:st=58:d=2 [1v]; \
[1:a] afade=t=in:st=0:d=2, afade=t=out:st=58:d=2 [1a]; \
[3:v] fade=t=in:st=0:d=2, fade=t=out:st=118:d=2 [3v]; \
[3:a] afade=t=in:st=0:d=1, afade=t=out:st=118:d=2 [3a]; \
[0:v] [0:a] [1v] [1a] [2:v] [2:a] [3v] [3a] [4:v] [4:a] concat=n=5:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" -c:v libx264 -c:a aac output.mp4
Объяснение:
-i
), которые мы будем конкатенировать-filter_complex
), который мы используем для:
fade
(для видео) и afade
(для аудио). Мы указываем начало ( st
) и продолжительность ( d
) для каждого затухания. Мы выводим результаты с внешними именами ( [1v]
, [1a]
...).concat
фильтр. Мы указываем количество входных сегментов n
(т. е. количество наборов видео+аудио, в нашем случае 5), которые мы хотим объединить, и количество видео ( v=1
) и аудио ( a=1
) потоков для вывода.map
окончательный вывод в выходные потоки из фильтра concatВажные заметки:
s
и n
(видео) или ss
и ns
(аудио). См . документацию по фильтрам затухания и затухания .Если вам действительно нужен однострочный (и вам не нужно кодировать пустые черные клипы), вы можете использовать:
ffmpeg \
-f lavfi -t 1 -i "color=black:s=1920x1080:r=30" -f lavfi -t 1 -i "anullsrc=r=48000:cl=2" \
-i part_1.mp4 \
-f lavfi -t 3 -i "color=black:s=1920x1080:r=30" -f lavfi -t 3 -i "anullsrc=r=48000:cl=2" \
-i part_2.mp4 \
-f lavfi -t 1 -i "color=black:s=1920x1080:r=30" -f lavfi -t 1 -i "anullsrc=r=48000:cl=2" \
-filter_complex \
"[0:v] null [0v]; [1:a] anull [0a]; [3:v] null [2v]; [4:a] anull [2a]; \
[6:v] null [4v]; [7:a] anull [4a]; \
[2:v] fade=t=in:st=0:d=2, fade=t=out:st=58:d=2 [1v]; \
[2:a] afade=t=in:st=0:d=2, afade=t=out:st=58:d=2 [1a]; \
[5:v] fade=t=in:st=0:d=1, fade=t=out:st=118:d=2 [3v]; \
[5:a] afade=t=in:st=0:d=1, afade=t=out:st=118:d=2 [3a]; \
[0v] [0a] [1v] [1a] [2v] [2a] [3v] [3a] [4v] [4a] concat=n=5:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" -c:v libx264 -c:a aac output.mp4
В этом случае мы должны остерегаться входных индексов , так как черные видеоклипы и нулевые аудиоклипы являются отдельными входными данными (я не понял, как поместить их как два потока в один вход, если у вас есть идея, не стесняйтесь поделиться Это).
null
Здесь я применил anull
фильтры к этим входам, чтобы дать им внешние теги, чтобы использовать согласованные идентификаторы в concat
фильтре. Но это чисто опционально.
Надеюсь, это поможет, не стесняйтесь улучшать мое решение с помощью ваших идей :)
Гьян