ffmpeg verbinde zwei mp4-Dateien mit ffmpeg auf der Kommandozeile

28

Ich kann mit dem folgenden Befehl mehrere Dateien erfolgreich verbinden:

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

Das einzige Problem bei diesem Befehl ist, dass Sie die Dateipfade aus der Textdatei input.txt mit folgendem Inhalt lesen müssen :

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'

Gibt es eine Möglichkeit, dasselbe Ziel zu erreichen, ohne die Dateipfade aus einer Datei lesen zu müssen? Ich habe folgendes ohne Glück versucht:

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

Muss ich einen anderen Befehl verwenden?

Fabio Delarias
quelle
1
related: stackoverflow.com/questions/7333232/…
Ciro Santilli Am

Antworten:

36

Update 2019:

Wie in den Kommentaren erwähnt, enthält Stack Overflow eine ausführliche Beschreibung der verfügbaren Optionen für die Verkettung sowie eine Erläuterung der zu verwendenden Methode in Abhängigkeit von den von Ihnen verwendeten Dateitypen:

Wie verkette ich zwei MP4-Dateien mit FFmpeg?

Original 2016 Antwort:

Sie sollten die concat-Protokollmethode verwenden können, um die Dateien zu kombinieren:

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

Darüber hinaus wird im FFmpeg-Handbuch eine Methode speziell für MP4-Dateien beschrieben, um diese verlustfrei zu verketten. Sie müssen jedoch temporäre Dateien (oder Named Pipes) erstellen:

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
Carson Liebling
quelle
1
Der erste Befehl funktionierte für mich wie eine Butter. Es dauerte 2 bis 3 Sekunden, um meine 6 mp4-Dateien in eine Ausgabedatei (ca. 239 MB) zu konvertieren.
Sachin
22
Der erste Befehl hat bei mir nicht funktioniert. Es wurde nur die erste Datei kopiert.
Luis A. Florit
3
Das funktioniert nicht, es kopiert nur die erste Datei nach output.mp4.
crmpicco
2
Die Verkettung auf Dateiebene funktioniert nicht für MP4, daher wird das Concat-Protokoll für dieses Format nicht empfohlen und funktioniert im Allgemeinen nicht.
Logan
1
@brasofilo Danke für den Link. Das ist längst überfällig, aber ich habe die Antwort aktualisiert, um die Leute in diese Richtung zu weisen.
Carson Darling
5

Sie können eine Datei durch eine Liste ersetzen, indem Sie eine Liste ausgeben stdoutund die Liste stdinvon ffmpeg lesen :

(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
quelle
Bei Verwendung von ffmpeg Version 2.4.3-tessus unter Mac OS 10.12.6 wird lediglich ein Fehler ausgegeben: "Nicht erkannte Option 'protocol_whitelist'". Ohne die Option protocol_whitelist scheint es nur eine Kopie der zweiten MP4-Datei zu geben.
James
2

Nein, es scheint keine Möglichkeit zu geben, den ffmpeg concat-Demuxer ohne Hack auf einer einzigen Befehlszeile zu verwenden. Sie müssen die Eingabetextdatei mit der Liste der Dateien erstellen. Ich fand das seltsam, vielleicht fügt jemand dies zu einem späteren Zeitpunkt zu FFMpeg hinzu.

Die akzeptierte Antwort auf diese Frage verwendet das Concat-Protokoll, nicht den Concat-Demuxer, den das OP gestellt hat.

Georgiecasey
quelle
1
Eigentlich gibt es. stdin.
Qwertiy
Das concat-Protokoll sollte nicht mit MP4 oder einem anderen Format verwendet werden, das einen globalen Header erfordert.
18.
1

Sie können dies immer noch in einem Skript tun, ohne den Befehl zu ändern. So etwas wie:

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.

Das $$ wird auf die PID der Shell erweitert, in der der Befehl ausgeführt wird, sodass der Dateiname bei jeder Ausführung anders ist. Wenn Sie möchten, können Sie $$. txt verwenden. Oder etwas anderes...

Sie können hier auch Dateien verwenden, um der Datei eine Reihe von Daten hinzuzufügen:

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

bash Die Variablensubstitution funktioniert, sodass Sie den Inhalt der Datei programmgesteuert bestimmen können. Eine Korrektur ist nicht erforderlich. Ich binde solche Sachen die ganze Zeit in for-Schleifen ein. Schließlich funktioniert die Umleitung wie oben beschrieben.> $$. Tmp schneidet ab und schreibt dann, >> $$. Tmp hängt an.

Richard Betel
quelle
2
Die Frage lautet: "Gibt es eine Möglichkeit, dasselbe Ziel zu erreichen, ohne die Dateipfade aus einer Datei lesen zu müssen?" Sie haben lediglich eine Möglichkeit bereitgestellt, die Dateipfade in eine Datei zu schreiben (bevor Sie die Dateipfade aus der Datei lesen). Dies beantwortet die Frage nicht.
Scott