it-swarm.com.de

Wie verketten Sie zwei MP4-Dateien mit FFmpeg?

Ich versuche, zwei mp4-Dateien mit ffmpeg zu verketten. Ich brauche einen automatischen Prozess, weshalb ich mich für ffmpeg entschieden habe. Ich konvertiere die beiden Dateien in .ts-Dateien, verkette diese und versuche dann, die betreffende .ts-Datei zu kodieren. Die Dateien sind h264 und aac codiert und ich hoffe, dass die Qualität gleich bleibt oder so nahe wie möglich am Original liegt.

ffmpeg -i part1.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part1.ts
ffmpeg -i part2.mp4 -vcodec copy -vbsf h264_mp4toannexb -acodec copy part2.ts
cat part1.ts part2.ts > parts.ts
ffmpeg -y -i parts.ts -acodec copy -ar 44100 -ab 96k -coder ac -vbsf h264_mp4toannexb parts.mp4

Leider erhalte ich folgende Fehlermeldung, die während der Codierung von ffmpeg zurückkommt:

[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[h264 @ 0x1012600]sps_id out of range
[h264 @ 0x1012600]non-existing SPS 0 referenced in buffering period
[NULL @ 0x101d600]error, non monotone timestamps 13779431 >= 13779431kbits/s    
av_interleaved_write_frame(): Error while opening file

Dies geschieht etwa zur Hälfte der Codierung, was mich zu dem Gedanken verleitet, dass Sie nicht zwei .ts-Dateien zusammenfassen können, damit es funktioniert.

233
Mark L

Ich habe am Ende mpg als Zwischenformat verwendet und es hat funktioniert (HINWEIS: Dies ist ein gefährliches Beispiel, -qscale 0 wird das Video neu codieren ...)

ffmpeg -i 1.mp4 -qscale 0 1.mpg
ffmpeg -i 2.mp4 -qscale 0 2.mpg
cat 1.mpg 2.mpg | ffmpeg -f mpeg -i - -qscale 0 -vcodec mpeg4 output.mp4
30
Mark L

FFmpeg verfügt über drei Verkettungsmethoden.

1. concat Videofilter

ffmpeg -i opening.mkv -i episode.mkv -i ending.mkv \
  -filter_complex "[0:v] [0:a] [1:v] [1:a] [2:v] [2:a] concat=n=3:v=1:a=1 [v] [a]" \
  -map "[v]" -map "[a]" output.mkv

Beachten Sie, dass diese Methode eine Neucodierung durchführt.

2. concat demuxer

$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

$ ffmpeg -f concat -i mylist.txt -c copy output

für Windows:

(echo file 'first file.mp4' & echo file 'second file.mp4' )>list.txt
ffmpeg -safe 0 -f concat -i list.txt -c copy output.mp4

3. concat Protokoll

ffmpeg -i "concat:input1|input2" -codec copy output

Diese Methode funktioniert aufgrund der Beschaffenheit dieser Formate und der durch diese Methode durchgeführten einfachen Verkettung nicht für viele Formate, einschließlich MP4.

Welches zu benutzen

  • concat filter: Verwenden Sie diese Option, wenn Ihre Eingaben nicht dieselben Parameter (Breite, Höhe usw.) aufweisen oder nicht dieselben Formate/Codecs aufweisen oder wenn Sie eine Filterung durchführen möchten. (Sie könnten nur die Eingänge neu codieren, die nicht übereinstimmen, so dass sie denselben Codec und andere Parameter verwenden, und dann den concat-Demuxer verwenden, um zu vermeiden, dass die anderen Eingänge erneut codiert werden.).

  • concat demuxer: Verwenden Sie diese Option, wenn Sie eine erneute Kodierung vermeiden möchten und Ihr Format keine Verkettung auf Dateiebene unterstützt (die meisten von allgemeinen Benutzern verwendeten Dateien unterstützen keine Verkettung auf Dateiebene).

  • concat protocol: Wird mit Formaten verwendet, die die Verkettung auf Dateiebene unterstützen (MPEG-1, MPEG-2 PS, DV). Verwenden Sie nicht mit MP4.

Im Zweifelsfall versuchen Sie den concat Demuxer.

Siehe auch

478
rogerdpack

Hier ist eine schnelle (weniger als 1 Minute dauernde) und verlustfreie Möglichkeit, dies ohne Zwischendateien zu tun:

ls Movie_Part_1.mp4 Movie_Part_2.mp4 | Perl -ne 'print "file $_"' | ffmpeg -f concat -i - -c copy Movie_Joined.mp4

Das "ls" enthält die zu verbindenden Dateien Das "Perl" erstellt die Verkettungsdatei in einer Pipe Der "-i -" - Teil weist ffmpeg an, aus der Pipe zu lesen

(Hinweis - Meine Dateien enthielten keine Leerzeichen oder seltsamen Sachen - Sie benötigen ein entsprechendes Shell-Escaping, wenn Sie diese Idee mit "harten" Dateien ausführen möchten).

45
cnd

FÜR MP4-DATEIEN

Für .mp4 -Dateien (die ich von DailyMotion.com erhalten habe: eine 50-minütige TV-Episode, die nur in drei Teilen als drei .mp4-Videodateien heruntergeladen werden kann), war das Folgende eine wirksame Lösung für Windows 7, und NICHT beinhaltet das Umcodieren der Dateien.

Ich habe die Dateien umbenannt (als file1.mp4, file2.mp4, file3.mp4), so dass die Teile in der richtigen Reihenfolge waren, um die komplette TV-Episode anzuzeigen.

Dann habe ich eine einfache Batchdatei (concat.bat) mit folgendem Inhalt erstellt:

:: Create File List
echo file file1.mp4 >  mylist.txt 
echo file file2.mp4 >> mylist.txt
echo file file3.mp4 >> mylist.txt

:: Concatenate Files
ffmpeg -f concat -i mylist.txt -c copy output.mp4

Die Stapeldatei und ffmpeg.exe müssen sich in demselben Ordner befinden wie die .mp4-Dateien, die verbunden werden sollen. Führen Sie dann die Batchdatei aus. Das Ausführen dauert normalerweise weniger als zehn Sekunden.

Addendum (2018/10/21) -

Wenn Sie nach einer Methode suchen, mit der Sie alle mp4-Dateien im aktuellen Ordner angeben können, ohne viele Eingaben wiederholen zu müssen, versuchen Sie es in Ihrem Windows Batchdatei stattdessen (MUSS include die Option -safe 0):

:: Create File List
for %%i in (*.mp4) do echo file '%%i'>> mylist.txt

:: Concatenate Files
ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Dies funktioniert unter Windows 7 in einer Batchdatei. Nicht Versuchen Sie es in der Kommandozeile, weil es nur in einer Batch-Datei funktioniert!

40
Ed999

für MP4-Dateien:

Wenn sie nicht exakt die gleichen MP4-Dateien (100% gleicher Codecs, gleiche Auflösung, gleicher Typ) sind, müssen Sie sie zunächst in Zwischenströme umcodieren:

ffmpeg -i myfile1.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp1.ts
ffmpeg -i myfile2.mp4 -c copy -bsf:v h264_mp4toannexb -f mpegts temp2.ts
// now join
ffmpeg -i "concat:temp1.ts|temp2.ts" -c copy -bsf:a aac_adtstoasc output.mp4

HINWEIS! : Die Ausgabe erfolgt wie die erste Datei (und keine zweite).

33
T.Todua

Ich habe versucht, drei .mp3-Audiodateien in einer .m4a-Datei zu verketten, und dieser Befehl ffmpeg funktioniert. 

Eingabebefehl:

ffmpeg -i input1.mp3 -i input2.mp3 -i input3.mp3 -filter_complex concat=n=3:v=0:a=1 -f MOV -vn -y input.m4a

Bedeutungen von: "-filter_complex concat = n = 3: v = 0: a = 1"

concat bedeutet, dass die Funktion zum Verketten von Medien (Verbinden) verwendet wird.
n bedeutet die Gesamtanzahl der Eingabedateien.
v bedeutet hat Video? Verwenden Sie 0 = kein Video, 1 = enthält Video.
a bedeutet hat Audio? Verwenden Sie 0 = kein Audio, 1 = Audio enthalten.
-f bedeutet das gesetzte Dateiformat erzwingen (verwenden Sie ffmpeg -formats, um alle unterstützten Formate anzuzeigen)
-vn bedeutet Video deaktivieren (und auch -an würde das Audio deaktivieren, wenn es nicht gewünscht wird)
-y bedeutet Ausgabedateien überschreiben (falls die Ausgabedatei bereits vorhanden ist).

Weitere Informationen: Verwenden Sie ffmpeg -h full Alle Optionen drucken (einschließlich aller Format- und Codec-spezifischen Optionen, sehr lang).

30
Ellie Tam

Eine ausführliche Dokumentation zu den verschiedenen Verkettungsmöglichkeiten in ffmpeg finden Sie hier .

Sie können 'Concat-Filter' für eine schnelle Verkettung verwenden.

Es führt eine Neucodierung durch. Diese Option ist am besten, wenn die Eingänge unterschiedliche Video-/Audioformate haben.

Zum Verketten von 2 Dateien: 

ffmpeg -i input1.mp4 -i input2.webm \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] concat=n=2:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Für die Verkettung von 3 Dateien: 

ffmpeg -i input1.mp4 -i input2.webm -i input3.mp4 \
-filter_complex "[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]" \
-map "[v]" -map "[a]" output.mp4

Dies funktioniert sowohl für gleiche als auch für mehrere Eingabedateitypen. 

11
SJ00

Ich stellte fest, dass der Pipe-Operator für mich nicht funktioniert hat, als ich in der akzeptierten Antwort Option 3 verwendet habe, um mehrere MP4s auf einem Mac zu verbinden.

Der folgende Einzeiler funktioniert auf einem Mac (High Sierra) zur Verkettung von MP3-Dateien, ohne dass eine zwischenzeitliche Dateierstellung erforderlich ist.

ffmpeg -f concat -safe 0 -i <(for f in ./*.mp4; do echo "file '$PWD/$f'"; done) -c copy output.mp4

6
Ben Siver

basierend auf den Antworten von Rogerdpack und Ed999 habe ich meine .sh-Version erstellt

#!/bin/bash

[ -e list.txt ] && rm list.txt
for f in *.mp4
do
   echo "file $f" >> list.txt
done

ffmpeg -f concat -i list.txt -c copy joined-out.mp4 && rm list.txt

es fügt alle *.mp4-Dateien im aktuellen Ordner in joined-out.mp4 zusammen

getestet auf mac.

die resultierende Dateigröße ist die exakte Summe meiner 60 getesteten Dateien. Sollte kein Verlust sein. Genau das, was ich brauchte

3

Hier ist ein Skript, das ich gemacht habe, um mehrere GoPro-mp4-Dateien in einem 720p-mp4-Format zu verketten. Ich hoffe es hilft.

#!/bin/sh
cmd="( "
for i; do
    cmd="${cmd}ffmpeg -i $i -ab 256000 -vb 10000000 -mbd rd -trellis 2 -cmp 2 -subcmp 2 -g 100 -f mpeg -; "
done
cmd="${cmd} ) | ffmpeg -i - -vb 10000000 -ab 256000 -s 1280x720 -y out-`date +%F-%H%M.%S`.mp4"
echo "${cmd}"
eval ${cmd}
3
Reid Ellis

Aus der Dokumentation hier: https://trac.ffmpeg.org/wiki/Concatenate

Wenn Sie MP4-Dateien haben, können diese losslessly verkettet werden, indem Sie sie zunächst in MPEG-2-Transportströme umcodieren. Bei H.264-Video und AAC-Audio kann Folgendes verwendet werden:

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

Dieser Ansatz funktioniert auf allen Plattformen.

Ich brauchte die Möglichkeit, dies in einem plattformübergreifenden Skript zu kapseln. Daher verwendete ich fluent-ffmpeg und kam zu folgender Lösung:

const unlink = path =>
  new Promise((resolve, reject) =>
    fs.unlink(path, err => (err ? reject(err) : resolve()))
  )

const createIntermediate = file =>
  new Promise((resolve, reject) => {
    const out = `${Math.random()
      .toString(13)
      .slice(2)}.ts`

    ffmpeg(file)
      .outputOptions('-c', 'copy', '-bsf:v', 'h264_mp4toannexb', '-f', 'mpegts')
      .output(out)
      .on('end', () => resolve(out))
      .on('error', reject)
      .run()
  })

const concat = async (files, output) => {
  const names = await Promise.all(files.map(createIntermediate))
  const namesString = names.join('|')

  await new Promise((resolve, reject) =>
    ffmpeg(`concat:${namesString}`)
      .outputOptions('-c', 'copy', '-bsf:a', 'aac_adtstoasc')
      .output(output)
      .on('end', resolve)
      .on('error', reject)
      .run()
  )

  names.map(unlink)
}

concat(['file1.mp4', 'file2.mp4', 'file3.mp4'], 'output.mp4').then(() =>
  console.log('done!')
)
3
itslittlejohn

Alle mp4-Dateien aus dem aktuellen Verzeichnis zusammenführen

Ich persönlich mag es nicht, eine externe Datei zu erstellen, die ich anschließend löschen muss. Daher wurde meine Lösung verfolgt, die eine Liste mit Dateinummern enthält (wie file_1_name, file_2_name, file_10_name, file_20_name, file_100_name, ...).

#!/bin/bash
filesList=""
for file in $(ls -1v *.mp4);do #lists even numbered file
    filesList="${filesList}${file}|"
done
filesList=${filesList%?} # removes trailing pipe
ffmpeg -i "concat:$filesList" -c copy $(date +%Y%m%d_%H%M%S)_merged.mp4
1
Pipo

das funktionierte für mich (unter Windows)

ffmpeg -i "concat:input1|input2" -codec copy output

im Speziellen

ffmpeg -i "concat:01.mp4|02.mp4" -codec copy output.mp4

Python

Wenn Sie Python-Code verwenden, um so viele mp4-Dateien in einem Ordner zu speichern, wie

stringa = ""
for f in glob.glob("*.mp4"):
    stringa += f + "|"

os.system("ffmpeg -i \"concat:" + stringa + "\" -codec copy output.mp4")
1
Giovanni Gianni
ffmpeg \
  -i input_1.mp4 \
  -i input_2.mp4 \
  -filter_complex '[0:v]pad=iw*2:ih[int];[int][1:v]overlay=W/2:0[vid]' \
  -map [vid] \
  -c:v libx264 \
  -crf 23 \
  -preset veryfast \
  output.mp4
1
Deepak Kumar

Das hier beschriebene concat-Protokoll; https://trac.ffmpeg.org/wiki/Concatenate#protocol

Bei der Implementierung mit Named Pipes, um Zwischendateien zu vermeiden

Ist sehr schnell (read: instant), hat keine Frames fallen gelassen und funktioniert gut.

Denken Sie daran, die Named Pipe-Dateien zu löschen und zu prüfen, ob es sich bei dem Video um H264 und AAC handelt, was Sie mit nur ffmpeg -i filename.mp4 tun können (prüfen Sie, ob h264 und aac Erwähnungen vorliegen).

0

Hier ist meine Methode zum Verbinden eines Verzeichnisses voller MP4-Dateien mithilfe der Befehlssubstitution und des Concat-Videofilters (dieser wird neu codiert) - es wird angenommen, dass jemand anderes von diesem Einzeiler Gebrauch macht, insbesondere wenn Sie viele Dateien haben (ich nur) 17 Dateien auf einen Schlag zusammengefügt):

ffmpeg $(for f in *.mp4 ; do echo -n "-i $f "; done) -filter_complex \
"$(i=0 ; for f in *.mp4 ; do echo -n "[$i:v] [$i:a] " ; i=$((i+1)) ; done \
&& echo "concat=n=$i:v=1:a=1 [v] [a]")" -map "[v]" -map "[a]" output.mp4

N.B. Dieser Befehl fügt Ihre Dateien in der Reihenfolge zusammen, in der sie benannt sind (d. h. in der Reihenfolge, in der sie angezeigt werden, wenn Sie ls *.mp4 ausführen).

0
Peter

Für .mp4-Dateien habe ich festgestellt, dass die Verwendung des Befehlszeilen-Tools "opensource" besser und schneller funktioniert: mp4box. Dann können Sie es folgendermaßen verwenden:

mp4box.exe -add video1.mp4 -cat video2.mp4 destvideo.mp4

Laden Sie es hier für die meisten Plattformen herunter: https://gpac.wp.imt.fr/mp4box/

0
Mario

Nach verschiedenen Versuchen unten funktionierte das Skript für mich auf Windows 10 Powershell.

    $files=Get-ChildItem -path e:\ -Filter *.mp4


    $files| ForEach-Object  {"file '$($_.FullName)'"}| Out-File -FilePath e:\temp.txt -Encoding ASCII


    if (-not (test-path "e:\ffmpeg\bin\ffmpeg.exe")) {throw "e:\ffmpeg\bin\ffmpeg.exe needed"}

    E:\ffmpeg\bin\ffmpeg.exe -safe 0 -f concat -i "e:\temp.txt" -c copy -bsf:v hevc_mp4toannexb -an e:\joined.mp4

    # Conversion Cleanup
    Remove-Item e:\temp.txt

Hier erzeugen die ersten beiden Zeilen eine Textdatei temp.txt mit folgendem Inhalt

file 'e:\first.mp4'
file 'e:\second.mp4'

3., 4. Zeile prüft ob ffmpeg im Pfad verfügbar ist und erstellt die "join.mp4"

Die wichtigsten Unterschiede zu anderen Antworten sind nachfolgend aufgeführt

usage  of -bsf:v hevc_mp4toannexb -an

für meine oben aufgeführte mp4-Datei müssen Sie abhängig von Ihrer Videokodierung möglicherweise andere Alternativen wie die folgenden verwenden.

h264_mp4toannexb

Alle möglichen Bitstream-Filter finden Sie unter https://ffmpeg.org/ffmpeg-bitstream-filters.html

0
rahul maindargi