FFmpeg Video teilen und wieder zusammenführen

8

Ich versuche, FFmpeg zu verwenden, um Videos basierend auf einigen start_timeund end_timeEingaben zu teilen und diese durch andere Videodateien zu ersetzen. Zum Beispiel muss 10 15ich für die Eingabe GENAUE Sekunden 10 to 15durch ein anderes Video ersetzen .

OK. Was mir in den Sinn kommt, ist Folgendes:

  1. Teilen Sie zuerst das Video (in diesem Fall 0-10, 10-15 und 15-Ende).
  2. Ersetzen Sie die 10-15 durch das andere Video
  3. Füge alle Untervideos wieder zusammen

Erste Frage: Ist dies die beste und schnellste Lösung? Haben wir einen einfacheren Befehl oder andere Tools, um einen bestimmten Zeitraum im Video durch ein anderes Video zu ersetzen?

Zweite Frage: Angenommen, FFmpeg ist die praktikable Lösung. Wenn ich einfach den Befehl verwende ffmpeg -I input.video -ss 10 -t 5 -c copy output.mp4, kann mein Videoverarbeitungscode die Datei nicht lesen und verarbeiten. Ich habe das mediainfoTool verwendet, um die beiden Dateien zu vergleichen, und habe Unterschiede in den Headergrößen festgestellt, während alle Video-Codec-bezogenen Inhalte gleich waren. Ich habe festgestellt, dass die HEADER-GRÖSSE unterschiedlich ist, was anscheinend das Problem verursacht. Gibt es Möglichkeiten, die Headergröße (abgesehen von Codecs) gleich zu machen?

UPDATE: Hier ist die Originaldatei .mp4, die im Emulator einwandfrei funktioniert.

Ariana
quelle
Zuerst müssten wir uns mit dem Problem befassen, das Sie in Ihrer zweiten Frage erwähnt haben. Bitte zeigen Sie den genauen Befehl, den Sie verwenden, und die vollständige, ungeschnittene Befehlszeilenausgabe, die Sie von ffmpeg erhalten. Zeigen Sie auch alle tatsächlichen Fehler an, die beim Lesen der Datei auftreten - es wäre gut zu wissen, was Ihr "Verarbeitungscode" genau ist.
Slhck
@slhck der Videoverarbeitungscode ist eine riesige Codebasis. Ich kann es nicht teilen. Es ist nur so, dass aus bestimmten Gründen die Originaldatei gelesen wird, aber nicht die neu generierte. Ich kann jedoch die Originaldatei .mp4bei Bedarf freigeben.
Ariana
Ich habe das mediainfo-Tool verwendet, um die beiden Dateien zu vergleichen und Unterschiede in den Headergrößen und -materialien festzustellen
Ariana
Das Original zu haben würde helfen, aber wir werden nicht in der Lage sein, Fehler zu beheben, warum es nicht gelesen werden kann, ich fürchte, wenn das ein interner Code ist.
Slhck
@slhck Ich habe die Datei hochgeladen. Meine Frage wurde aktualisiert
Ariana

Antworten:

9

Verwenden von trimund concat- Quelldateien mit verschiedenen Codecs

Stellen Sie dazu sicher, dass Ihre einzelnen Dateien dieselbe Auflösung und im Idealfall dieselbe Framerate und Chroma-Unterabtastung usw. haben. Dies verhindert Fehler oder Störungen während der Verkettung.

Mit den Filtern trimund können Sie alles auf einmal erledigen, ohne die Datei zu teilen 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

Hier werden trimdie einzelnen Teile der Eingangsvideostreams ( 0:v, 1:v) angegeben, die Sie später verketten möchten. Diese Teile sind v0durch benannt v2. (Der setptsFilter setzt die Zeitstempel dieser einzelnen Teile auf 0 zurück, was für die Verkettung erforderlich ist.) Später verketten wir die drei Teile.

Wenn Sie von einem bestimmten Zeitstempel bis zum Ende trimmen möchten, verwenden Sie, trim=start=15anstatt den Bereich anzugeben.

Wenn Ihre Dateien Audio enthalten, müssen Sie diese Streams separat trimmen:

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

Beachten Sie, dass Video und Audio in diesem Fall neu codiert werden. -crfStellen Sie sicher, dass Sie die entsprechenden Ausgabequalitätsziele angeben (z. B. für x264, x265 oder libvpx-vp9). Weitere Informationen hierzu finden Sie im FFmpeg-Wiki, z. B. für VP9 oder H.264 .

Einzelne Segmente verwenden

Wenn Sie die Clips teilen und später wieder zusammensetzen möchten:

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

Wenn die Dateien Audio enthalten, verwenden Sie den gleichen Ansatz wie oben:

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

Dadurch wird der Videostream erneut neu codiert. Es ist etwas einfacher, sollte aber ansonsten der obigen Methode entsprechen.

Mit concatdemuxer

Sie können im Prinzip auch versuchen, die Bitströme mit dem concat-Demuxer zu verketten, ohne sie neu zu codieren. Erstellen Sie eine Datei mit dem Namen concat.txtund fügen Sie die folgenden Einträge hinzu (entsprechend den oben erstellten Videoclips):

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

Verketten Sie dann diese einzelnen Dateien:

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

Dies setzt jedoch voraus, dass Ihre Clips denselben Codec, dieselbe Auflösung, dieselbe Framerate usw. haben - daher funktioniert dies nicht mit allen Arten heterogener Quellen.

Mit concatProtokoll

Die obige Art der Verkettung auf Dateiebene kann auch unter Verwendung des concatProtokolls mit den gleichen Einschränkungen wie oben (gleicher Codec, Auflösung usw.) erreicht werden:

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

Weitere Informationen zur Verkettung finden Sie auf der entsprechenden FFmpeg-Wiki-Seite .

slhck
quelle
Das sieht sehr komplett aus! Vielen Dank. Ich werde sie versuchen!
Ariana
Idk, warum die Verwendung der concatMethode einen Fehler auslöst :[concat @ 00000000025c2560] Line 1: unknown keyword 'part1.mp4 \\ text.txt: Invalid data found when processing input
Ariana
Für "Verwenden einzelner Segmente" sehe ich einen Stopp und einen kleinen Ausschnitt der Ausgabe. Gibt es Möglichkeiten, dies zu beheben?
Ariana
Methode 1 funktioniert perfekt. Eine Sache: Wie können wir "bis zum Ende" angeben, ohne eine bestimmte Nummer anzugeben (anstelle von 30 s)
Ariana
1
Entschuldigung, habe einen Fehler gemacht. Für den concatDemuxer war die Syntax anders. Jetzt behoben. Gehen bis zum Ende, Verwendung trim=start=15finden Sie in der Trimm - Filter Dokumentation: ffmpeg.org/ffmpeg-filters.html#trim - wie für Timing - Probleme, das ist wirklich hängt von Ihrem Quellmaterial. Es gab jedoch keine Probleme beim Verketten mit dem hochgeladenen Clip.
Slhck