Verbinden Sie mp4-Dateien unter Linux

31

Ich möchte zwei mp4-Dateien zusammenfügen, um eine einzige zu erstellen. Die Videostreams sind in h264 und die Audiodaten in aac codiert. Ich kann die Videos aus rechentechnischen Gründen nicht in ein anderes Format umcodieren. Ich kann auch keine GUI-Programme verwenden. Die gesamte Verarbeitung muss mit Linux-Befehlszeilenprogrammen durchgeführt werden. FFmpeg kann dies nicht für mpeg4-Dateien tun, daher habe ich stattdessen MP4Box verwendet:

MP4Box -add video1.mp4 -cat video2.mp4 newvideo.mp4

Leider ist der Ton völlig durcheinander. Ich dachte, dass das Problem war, dass das Audio in AAC war, also habe ich es in MP3 transkodiert und wieder MP4Box verwendet. In diesem Fall ist das Audio für die erste Hälfte von newvideo.mp4(entsprechend video1.mp4) in Ordnung , aber dann ist es kein Audio und ich kann auch nicht im Video navigieren.

Mein nächster Gedanke war, dass die Audio- und Videostreams einige kleine Abweichungen in ihrer Länge aufwiesen, die ich beheben sollte. Also habe ich für jedes Eingangsvideo die Video- und Audiostreams aufgeteilt und sie dann mit der Option -shortest in FFmpeg verbunden.

So lief ich für das erste Video:

 avconv -y -i video1.mp4 -c copy -map 0:0 videostream1.mp4
 avconv -y -i video1.mp4 -c copy -map 0:1 audiostream1.m4a
 avconv -y -i videostream1.mp4 -i audiostream1.m4a  -c copy -shortest  video1_aligned.mp4

Ähnliches gilt für das zweite Video und dann verwendete MP4Box wie bisher. Leider hat das auch nicht geklappt. Der einzige Erfolg, den ich hatte, war, als ich die Videostreams separat (dh videostream1.mp4 und videostream2.mp4) und die Audiostreams (dh audiostream1.m4a und audiostream2.m4a) zusammengefügt und dann das Video und Audio in einer endgültigen Datei zusammengefügt habe. Die Synchronisation geht jedoch für die zweite Hälfte des Videos verloren. Konkret gibt es eine Verzögerung von 1 Sekunde für Audio und Video. Anregungen sind sehr willkommen.

Jose Armando
quelle
"FFmpeg kann dies nicht für MPEG4-Dateien tun, also habe ich stattdessen MP4Box verwendet" meinst du MP4-Datei? Verwenden beide Audio-Video-Streams dieselben Codierungsparameter (Breite, Höhe, SPS, PPS, Bildrate, Abtastrate, Anzahl der Kanäle?
Mit ffprobe sehe ich, dass die Audio-Streams identische Attribute haben. Die Videostreams haben die gleichen Abmessungen, aber unterschiedliche Raten. Für das erste Video Video: h264, 720x592, 277 kb / s, PAR 18944: 12915 DAR 512: 287, 24,97 fps, 45k tbr, 90k tbn, 90k tbc, während für das zweite Video: h264, 720x592, 226 kb / s, PAR 481: 330 DAR 39:22, 24,91 fps, 45.000 tbr, 90.000 tbn, 90.000 tbc. Glauben Sie, dass dies die Ursache meiner Probleme ist?
MP4 unterstützt das Verbinden von Video / Audio mit unterschiedlichen Eigenschaften unter Verwendung unterschiedlicher Spuren für unterschiedliche Videos, aber die Player sind nicht so intelligent.
Rajneesh
Versuchen Sie dies stackoverflow.com/questions/5415006/…
Daya
Ihre Frage wurde bereits in den FAQ zu ffmpeg beantwortet: ffmpeg.org/faq.html#How-can-I-join-video-files_003f
Palec

Antworten:

31

Der beste Weg, dies zu tun, ist derzeit mit dem Concat-Demuxer . Erstellen Sie zunächst eine Datei mit dem Namen inputs.txtformatiert wie folgt:

file '/path/to/input1.mp4'
file '/path/to/input2.mp4'
file '/path/to/input3.mp4'

Führen Sie dann einfach diesen Befehl ffmpeg aus:

ffmpeg -f concat -i inputs.txt -c copy output.mp4

Siehe auch Verkettung in ffmpegFAQ .


Ich behalte hier die folgenden Informationen für alle, die ältere Versionen von ffmpeg verwenden.

Die neuesten Versionen von ffmpeg können dies: Sie müssen die Dateien zuerst in mpeg-Transportströme remuxen (ziemlich prozessorleicht, da nur das Containerformat geändert wird):

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

Wenn dies zu einem Fehler in Bezug auf h264 führt, müssen Sie möglicherweise Folgendes verwenden:

ffmpeg -i input.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb middle.ts

Sie müssen dies für jede Eingabedatei separat tun. Verwenden Sie zum Zusammenfügen der Dateien Folgendes:

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy output.mp4

Wenn das einen Fehler über AAC auslöst, müssen Sie möglicherweise verwenden

ffmpeg -i "concat:middle1.ts|middle2.ts|middle3.ts" -c copy -absf aac_adtstoasc output.mp4

Wenn Ihr System Named Pipes unterstützt, können Sie dies tun, ohne Zwischendateien zu erstellen.

mkfifo temp0 temp1

In drei separaten virtuellen Terminals müssen Sie Folgendes ausführen:

ffmpeg -i input0.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp0
ffmpeg -i input1.mp4 -map 0 -c copy -f mpegts -bsf h264_mp4toannexb -y temp1
ffmpeg -f mpegts -i "concat:temp0|temp1" -c copy -absf aac_adtstoasc output.mp4

Wenn die Datei output.mp4 bereits vorhanden ist, werden Sie vom dritten ffmpeg gefragt, ob Sie sie überschreiben möchten. Dies geschieht jedoch nach dem Zugriff auf die FIFOs. Dadurch werden die ersten ffmpegs geschlossen. Stellen Sie daher sicher, dass Sie einen nicht verwendeten Namen für Ihre Ausgabedatei auswählen.

Dies funktioniert möglicherweise nicht, wenn Ihre Eingabedateien unterschiedlich sind. Ich glaube, dass Unterschiede in der Bitrate in Ordnung sind, aber die Bildgröße, Bildrate usw. müssen übereinstimmen.

Übelsuppe
quelle
Vielen Dank, arbeitete wie ein Zauber
Jose Armando
2
@ DaveJarvis Nicht so; Dies ist eine absichtlich und böswillig verbreitete Nachricht des libav-Teams, einer Gruppe von Entwicklern, die sich vom ffmpeg-Projekt getrennt haben, um avconv zu entwickeln (und den Namen geändert haben, weil sie das Urheberrecht für den ffmpeg-Namen nicht sichern konnten). Siehe Wer kann mir den Unterschied und die Beziehung zwischen ffmpeg, libav und avconv erklären? für ein bisschen mehr Informationen.
Übelsuppe
2
*** THIS PROGRAM IS DEPRECATED *** This program is only provided for compatibility and will be removed in a future release. Please use avconv instead.ist eine Botschaft, die ich jetzt beim Laufen seheffmpeg
Lord Loh.
@LordLoh. Siehe den Link in meinem vorherigen Kommentar.
Übelsuppe
1
Diese Antwort antwortet nicht - wie man mp4 mitavconv
Lord Loh
7

Für MP4 war die einzige funktionierende Lösung, die ich gefunden habe, MP4Box von GPAC-Paket

#!/bin/bash
filesList=""
for file in $(ls *.mp4|sort -n);do
    filesList="$filesList -cat $file"
done
MP4Box $filesList -new merged_files_$(date +%Y%m%d_%H%M%S).mp4

oder Befehl ist

MP4Box -cat file1.mp4 -cat file2.mp4 -new mergedFile.mp4

mit mencoder und avconv konnte ich es nicht zum laufen bringen :-(

Philippe Gachoud
quelle
2

Danke für das Script dvo. Es war ein großartiger Ausgangspunkt für mich. Ich hatte kein Problem mit der Verwendung von Named Pipes, also habe ich das Skript angepasst, um sie stattdessen zu verwenden. Außerdem habe ich es repariert, um mit Dateinamen mit Leerzeichen zu arbeiten. Die Ausgabe in Named Pipes "geht" erst, wenn Sie mit dem Lesen beginnen. Daher müssen Sie die anfänglichen Remux-Tasks vor dem letzten Aufruf von avconv mit einem & hinterlegen. Vergessen Sie außerdem nicht, -c copy zu verwenden, da sonst die gesamte Menge neu codiert wird.

#!/bin/bash
for FILE in "$@"; do
   TAG=$(echo "$FILE" | sed -e s/[^A-Za-z0-9.]/_/g)
   mkfifo $TAG.mp4concatpipe
   avconv -loglevel "quiet" -i "$FILE"  -f mpegts -c copy -bsf h264_mp4toannexb -y $TAG.mp4concatpipe &
   IN=$IN\|$TAG.fifo
done

IN=${IN#\|}
avconv -i concat:$IN -c copy out.mp4
rm *.mp4concatpipe
Kennzeichen
quelle
Aus irgendeinem Grund gibt mir dies einen "concat: first.m4v.fifo | second.m4v.fifo: Keine solche Datei oder Verzeichnis" Fehler .. auch mit Anführungszeichen (-i concat: "$ IN" oder -i "concat: $ IN "). Die in der anderen Antwort unten vorgeschlagene MP4Box funktioniert jedoch hervorragend!
Vorburger
2

Auf einem Mac (macOS 10.13 High Sierra) habe ich mit Erfolg Folgendes verwendet:

for f in *.m4a; do echo "file '$f'" >> mylist.txt; done

Sortieren Sie wie oben beschrieben neu, falls erforderlich (beachten Sie, dass ./ entfernt wurde - der Pfad verursachte, dass ffmpeg den unsicheren Dateinamenfehler verursachte).

Dann musste ich den Codec und die Bitrate entfernen, die für das Standard-MacPorts-ffmpeg angegeben wurden, um es zu mögen:

ffmpeg -f concat -i mylist.txt  output.m4a
Robert Cole
quelle
Willkommen bei Super User! Bitte lesen Sie die Frage noch einmal sorgfältig durch. Ihre Antwort beantwortet nicht die ursprüngliche Frage, die sich mit Linux befasste. Wenn Sie glauben, dass es unter Linux funktionieren wird, fügen Sie dies bitte hinzu, damit zukünftige Leser ein klares Verständnis haben. Bitte nehmen Sie ein paar Minuten und lesen: - superuser.com/help .Answering: superuser.com/help/how-to-answer .
mic84
2

Hier ist ein Einzeiler, der alles noch einfacher macht. Es muss alles getan werden, um Ihnen endlich eine resultierende Videodatei zur Verfügung zu stellen. Prost!

find *.mp4 | sed 's:\ :\\\ :g'| sed 's/^/file /' > list.txt; ffmpeg -f concat -i list.txt -c copy output.mp4; rm list.txts
Anonym
quelle
1

Danke böse Suppe; Hier ist ein kleines Skript zur Automatisierung des Prozesses unter Verwendung der neueren avconv.
Übrigens, Named Pipes funktionierten bei mir nicht (die Ausgabe an sie blieb hängen).

   #!/bin/bash

    for FILE in $@; do
      avconv -i $FILE -map 0 -f mpegts -bsf h264_mp4toannexb -c:v copy -y $FILE.tmp
      IN=$IN\|$FILE.tmp
    done

    IN=${IN#\|}
    avconv -i concat:"$IN" out.mp4

    for FILE in $@; do
      rm $FILE.tmp
    done
dvo
quelle
0

Habe großen Erfolg mit genossen

for f in ./*.m4a; do echo "file '$f'" >> mylist.txt; done

Möglicherweise müssen Sie mylist.txt etwas neu anordnen

ffmpeg -f concat -i mylist.txt -c:a libfdk_aac -b:a 128k output.m4a

ffmpeg Version 2.2.3

Benjamin
quelle