Как объединить клипы из того же видео с помощью ffmpeg

15

У меня длинное видео с разными сценами. Я хочу извлечь и объединить 2 сцены из видео (которые не начинаются на I-кадре), используя ffmpeg 2.1.4.

Для аргумента скажем, я хочу 5 секунд с 01:00 и 02:00.

Я могу это сделать:

ffmpeg -ss 01:00 -i in.mkv -ss 02:00 -i in.mkv -filter_complex "
  [0:v]select='lt(t,5)'[v0];
  [0:a]aselect='lt(t,5)'[a0];
  [v0][a0][1:v][1:a]concat=n=2:v=1:a=1
" -c:a libvorbis -t 10 out.mkv

Это дает мне фильм, который я хочу, но на самом деле select заставляет ffmpeg декодировать весь оставшийся фильм. Итак, как мне сказать обрезать первый фильм вместо его декодирования?

Я бы предпочел сделать это с помощью комплексного фильтра ffmpeg, если это возможно. Я знаю, что -tсначала могу просто перекодировать отдельные фильмы, но в моем случае дополнительный шаг кодирования очень медленный, а также теряет изрядное количество качества для этого видео.

Я не могу найти фильтр, который усекает длину пара. Существуют ли узлы фильтра, которые соответствуют параметрам -tили -ss?

scubed
источник

Ответы:

16

Конкат фильтр

Этот метод лучше всего подходит, если вам необходимо выполнить дополнительную фильтрацию:

Используйте trim, atrim, setpts, asetpts, и concatфильтры:

ffmpeg -i input -filter_complex \
"[0:v]trim=60:65,setpts=PTS-STARTPTS[v0]; \
 [0:a]atrim=60:65,asetpts=PTS-STARTPTS[a0]; \
 [0:v]trim=120:125,setpts=PTS-STARTPTS[v1];
 [0:a]atrim=120:125,asetpts=PTS-STARTPTS[a1]; \
 [v0][a0][v1][a1]concat=n=2:v=1:a=1[out]" \
-map "[out]" output.mkv
  • setptsи asetptsпредотвратит прерывистый вывод из-за проблем с отметкой времени представления.

  • Убедитесь, что вы используете последнюю версию. См. Страницу загрузки FFmpeg для ссылок на сборки для Windows, OS X и Linux.


Concat DeMuxer

Другой метод состоит в том, чтобы создавать сегменты индивидуально и копировать их в потоковом режиме вместо перекодирования (чтобы сэкономить время и качество), и объединить их с демультиплексором concat .

$ ffmpeg -ss 60 -i input -t 5 -codec copy clip1.mkv
$ ffmpeg -ss 120 -i input -t 5 -codec copy clip2.mkv
$ echo "file 'clip1.mkv'" > concat.txt
$ echo "file 'clip2.mkv'" >> concat.txt
$ ffmpeg -f concat -i concat.txt -codec copy output.mkv
llogan
источник
2
Ах, спасибо. отделка - это то, чего мне не хватало. Тем не менее, требуется очень много времени, чтобы добраться до указанного мной смещения времени, как если бы он декодировал все до него. Также в части вывода отсутствовал звук. Чтобы исправить, я указывал один и тот же ввод несколько раз с помощью -ss, а затем использовал обрезку для усечения видео. В этом случае вам не нужны setpts, так как ss устанавливает pts в 0. Это, похоже, работает и не имеет странных случайных пауз во время кодирования. Что касается копирования потоков, я пробовал это раньше. Он начинается с предыдущего I-кадра, поэтому вы получаете другую часть фильма, чем вы хотели.
14:05
Не могли бы вы ответить на мой вопрос, он похож на этот. video.stackexchange.com/questions/18247/…
Эфтехари
Интересно -filter_complexработает, но concatфайлы нет - т.е. 1-е видео выглядит хорошо, но качество 2-го ужасно. Обратите внимание, я скопировал эти команды точно для обеих (кроме входного файла).
bobmarksie
7

Это должно работать быстрее ...

ffmpeg -ss 1:00 -t 5 -i in.mkv -ss 2:00 -t 5 -i in.mkv \
  -filter_complex "[0][1]concat=n=2:v=1:a=1" \ 
  out.mkv

Нет необходимости указывать -t на выходе. Там нет необходимости разделять аудио и видео перед концом.

Уильям Франц
источник
1
При этом используется фильтр concat, который потребует перекодирования. Это может или не может быть желательно пользователем.
Llogan