ffmpeg объединяет два файла mp4 с помощью ffmpeg в командной строке

26

Я могу успешно объединить несколько файлов, используя следующую команду:

ffmpeg -f concat -i input.txt -codec copy output.mp4

Единственная проблема с этой командой заключается в том, что вам нужно прочитать пути к файлам из текстового файла с именем input.txt следующего содержания:

file 'C:\Users\fabio\Downloads\Super\Sharks\01.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\02.mp4'
file 'C:\Users\fabio\Downloads\Super\Sharks\03.mp4'

Есть ли способ достичь той же цели, не считывая пути к файлам из файла? Я попробовал следующее без удачи:

ffmpeg -f concat -i file "C:\a\b\01.mp4" file "C:\a\b\02.mp4" -codec copy output.mp4
ffmpeg -f concat -i "C:\a\b\01.mp4" "C:\a\b\02.mp4" -codec copy output.mp4

Должен ли я использовать другую команду?

Фабио Делариас
источник
1
связанные: stackoverflow.com/questions/7333232/…
Сиро Сантилли 新疆 改造 中心 996ICU 六四 事件

Ответы:

35

2019 Обновление:

Как уже упоминалось в комментариях, в Stack Overflow есть отличное описание доступных опций конкатенации, а также обсуждение того, какой метод использовать в зависимости от типов файлов, которые вы используете:

Как объединить два файла MP4 с помощью FFmpeg?

Оригинальный ответ 2016 года:

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

ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4

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

ffmpeg -i input1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate1.ts
ffmpeg -i input2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts intermediate2.ts
ffmpeg -i "concat:intermediate1.ts|intermediate2.ts" -c copy -bsf:a aac_adtstoasc output.mp4
Карсон Дарлинг
источник
1
Первая команда работала для меня как масло ... потребовалось от 2 до 3 секунд, чтобы объединить мои 6 mp4 файлов в выходной файл (примерно 239 МБ).
Сачин
20
Первая команда не работает для меня. Он просто скопировал первый файл.
Луис А. Флорит
2
Это не работает, просто скопировал первый файл в output.mp4.
crmpicco
2
Конкатенация на уровне файлов не работает для MP4, поэтому протокол concat для этого формата не рекомендуется и обычно не работает.
Llogan
1
@brasofilo Спасибо за ссылку. Это давно пора, но я обновил ответ, чтобы указать людям в этом направлении.
Карсон Дарлинг
4

Вы можете заменить файл списком путем вывода списка stdoutи чтения списка из stdinffmpeg:

(echo file 'a.mp4' & echo file 'b.mp4') | ffmpeg -protocol_whitelist file,pipe -f concat -safe 0 -i pipe: -vcodec copy -acodec copy "result.mp4"
Qwertiy
источник
При использовании ffmpeg версии 2.4.3-tessus в Mac OS 10.12.6 это просто выдает ошибку: «Нераспознанная опция« protocol_whitelist »». Без опции protocol_whitelist кажется, что он просто делает копию второго файла MP4.
Джеймс
2

Нет, похоже, нет никакого способа использовать демультиплексор ffmpeg concat в одной командной строке без какого-либо взлома. Вам необходимо создать входной текстовый файл со списком файлов. Я сам подумал, что это странно, может быть, кто-то добавит это в FFMpeg позже.

Принятый ответ на этот вопрос использует протокол concat, а не дематер concat, о котором спрашивал OP.

georgiecasey
источник
1
На самом деле есть. STDIN.
Qwertiy
Протокол concat не должен использоваться с MP4 или любым другим форматом, для которого требуется глобальный заголовок.
Llogan
0

Вы все еще можете сделать это в сценарии без изменения команды. Что-то вроде:

echo "file fname1" >$$.tmp    #single redirect creates or truncates file
echo "file fname2" >>$$.tmp   # double redirect appends
echo "file fname3" >>$$.tmp   # do as many as you want.

ffmpeg -f concat -i $$.tmp -codec copy output.mp4

rm $$.tmp  # just to clean up the temp file. 
           # For debugging, I usually leave this out.

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

Кроме того, вы можете использовать здесь файлы, чтобы добавить кучу данных в файл:

cat <<EOF >$$.tmp
file fname1
file fname2
file fname3
EOF

bash Подстановка переменных работает, так что вы можете программно определять содержимое файла, это не нужно исправлять. Я постоянно внедряю подобные вещи в циклы. Наконец, перенаправление работает так же, как и выше, поэтому> $$. Tmp усекает, а затем пишет, >> $$. Tmp добавляется.

Ричард Бетел
источник
2
Вопрос спрашивает: «Есть ли способ достичь той же цели, не считывая пути к файлам из файла?» Все, что вы сделали, - это предоставили способ записи пути к файлу в файл (до чтения пути к файлу из файла). Это не отвечает на вопрос.
Скотт