FFmpeg разделить видео и объединить обратно

8

Я пытаюсь использовать FFmpeg, чтобы разделить видео на основе некоторых start_timeи end_timeвходов, и заменить их другими видеофайлами. Например, для ввода 10 15мне нужно заменить EXACT секунд 10 to 15на другое видео.

ХОРОШО. Что приходит мне в голову это:

  1. Сначала разделите видео (в данном случае 0-10, 10-15 и 15-конец)
  2. Заменить 10-15 другим видео
  3. Объединить все суб-видео обратно

Первый вопрос: это лучшее и самое быстрое решение? Есть ли у нас более простая команда или другие инструменты для замены определенного периода времени в видео другим видео?

Второй вопрос: если предположить, что FFmpeg является жизнеспособным решением, когда я просто использую команду ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, мой код обработки видео не может прочитать и обработать файл. Я использовал mediainfoинструмент для сравнения двух файлов и заметил различия в размерах заголовков, в то время как все, что связано с видеокодеком, было одинаковым. Я заметил, что размер заголовка отличается, что, очевидно, вызывает проблему. Есть ли способы заставить размер заголовка также (кроме кодеков) быть одинаковыми?

ОБНОВЛЕНИЕ: Вот оригинальный .mp4файл, который отлично работает в эмуляторе.

Ariana
источник
Сначала нам нужно разобраться с проблемой, которую вы упомянули во втором вопросе. Пожалуйста, покажите точную команду, которую вы используете, и полный, неразрезанный вывод командной строки, полученный из ffmpeg. Также покажите любые реальные ошибки, которые вы получаете при чтении файла - было бы хорошо знать, каков ваш «код обработки».
slhck
@slhck код обработки видео - огромная база кода. Я не могу поделиться этим. Просто по некоторым причинам исходный файл читается, а не сгенерированный заново. Однако я могу поделиться оригинальным .mp4файлом, если это необходимо.
Ариана
Я использовал инструмент mediainfo, чтобы сравнить два файла и заметить различия в размерах и
Ариана
Наличие оригинала поможет, но мы не сможем выяснить, почему его нельзя прочитать, боюсь, если это какой-то внутренний код.
Slhck
@slhck Я загрузил файл. Мой вопрос обновлен
Ариана

Ответы:

9

Использование trimи concat- исходные файлы с разными кодеками

Для этого убедитесь, что ваши отдельные файлы имеют одинаковое разрешение и в идеале одинаковую частоту кадров и частоту дискретизации и т. Д. Это предотвратит ошибки или сбои во время объединения.

Вы можете сделать все на одном дыхании , без разделения файла, используя trimи concatфильтры:

ffmpeg -i edv_g24.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[v0][v1][v2]concat=n=3:v=1:a=0[out]" \
-map "[out]" output.mp4

Здесь trimиспользуется для указания отдельных частей входных видеопотоков ( 0:v, 1:v), которые вы позже хотите объединить. Эти части названы до v0конца v2. ( setptsФильтр сбрасывает метки времени этих отдельных частей на 0, что требуется для объединения). Позже мы объединяем три части.

Если вы хотите обрезать определенную временную метку до конца, используйте trim=start=15вместо указания диапазона.

Если в ваших файлах есть аудио, вы должны обрезать эти потоки отдельно:

ffmpeg -i edv_g24_2.mp4 -i short-video.mp4 -filter_complex "\
[0:v]trim=0:10,setpts=PTS-STARTPTS[v0]; \
[0:a]atrim=0:10,asetpts=PTS-STARTPTS[a0]; \
[1:v]trim=0:5,setpts=PTS-STARTPTS[v1]; \
[1:a]atrim=0:5,asetpts=PTS-STARTPTS[v1]; \
[0:v]trim=15:30,setpts=PTS-STARTPTS[v2]; \
[0:a]atrim=15:30,asetpts=PTS-STARTPTS[a2]; \
[v0][a0][v1][a1][v2][a2]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" output.mp4

Обратите внимание, что видео и аудио будут перекодированы в этом случае - обязательно укажите соответствующие целевые показатели качества вывода (например, -crfдля x264, x265 или libvpx-vp9). Вы можете прочитать больше об этом в FFmpeg Wiki, например, для VP9 или H.264 .

Использование отдельных сегментов

Если вы хотите разделить клипы и позже собрать их:

ffmpeg -i edv_g24.mp4 -ss 0 -to 10 -c copy part1.mp4
ffmpeg -i edv_g24.mp4 -ss 10 -to 15 -c copy part2.mp4
ffmpeg -i edv_g24.mp4 -ss 15 -c copy part3.mp4

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][1:v][2:v]concat=n=3:v=1:a=0[outv]" \
-map "[outv]" -t 30 output.mp4

Если файлы имеют аудио, используйте тот же подход, что и выше:

ffmpeg -i part1.mp4 -i short-video.mp4 -i part3.mp4 -filter_complex \
"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" \
-map "[outv]" -map "[outa]" -t 30 output.mp4

Это снова перекодирует видео поток. Это немного более просто, но в остальном должно быть эквивалентно вышеуказанному методу.

Использование concatdemuxer

В принципе, вы также можете попытаться объединить битовые потоки без перекодирования, используя демультиплексор concat. Создайте файл с именем concat.txtи добавьте следующие записи (соответствующие созданным выше видеоклипам):

file 'part1.mp4'
file 'short-video.mp4'
file 'part3.mp4'

Затем объедините эти отдельные файлы:

ffmpeg -f concat -i concat.txt -c copy output.avi

Это, однако, требует, чтобы ваши клипы имели одинаковый кодек, разрешение, частоту кадров и т. Д., Поэтому он не работает со всеми видами разнородных источников.

Используя concatпротокол

Описанный выше тип конкатенации на уровне файлов также может быть достигнут с использованием concatпротокола с теми же ограничениями, что и выше (тот же кодек, разрешение и т. Д.):

ffmpeg -i "concat:part1.avi|part2.avi|part3.avi" -c copy output.mp4

Для получения дополнительной информации о сцеплении, прочитайте соответствующую страницу FFmpeg Wiki .

slhck
источник
Это выглядит очень полным! Спасибо. Я попробую их!
Ариана
ИДК почему при использовании concatметода выдает ошибку:[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ариана
Что касается «использования отдельных сегментов», я вижу остановку и небольшой отрезок вывода. Есть ли способы исправить это?
Ариана
Способ 1 работает отлично. Одно: как мы можем указать «до конца» без указания конкретного числа (вместо 30 с)
Ариана
1
Извините, ошибся. Для concatдемультиплексора синтаксис был другим. Исправлено сейчас. Чтобы перейти к концу, используйте trim=start=15документацию фильтра обрезки: ffmpeg.org/ffmpeg-filters.html#trim - что касается вопросов синхронизации, это действительно зависит от вашего исходного материала. У вас не было проблем с конкатенацией с загруженным вами клипом.
slhck