Schneiden der Videos basierend auf Start- und Endzeit mit ffmpeg


510

Ich habe versucht, das Video mithilfe der Start- und Endzeit des Videos mit dem folgenden Befehl zu schneiden

ffmpeg -ss 00:00:03 -t 00:00:08 -i movie.mp4 -acodec copy -vcodec copy -async 1 cut.mp4

Mit dem obigen Befehl möchte ich das Video von 00:00:03bis schneiden 00:00:08. Es wird jedoch nicht zwischen diesen Zeiten das Video geschnitten, sondern das Video mit den ersten 11 Sekunden. Kann mir jemand helfen, wie man das löst?

Bearbeiten 1:

Ich habe versucht, mit dem folgenden Befehl zu schneiden, der von mark4o vorgeschlagen wird

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Es wurde jedoch der folgende Fehler angezeigt.

Der Encoder 'aac' ist experimentell, aber experimentelle Codecs sind nicht aktiviert

-strict -2Also habe ich das in den Befehl eingefügt, dh

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -strict -2 cut.mp4

Jetzt funktioniert es gut.


3
Ihre vollständige, ungeschnittene ffmpeg-Konsolenausgabe fehlt. Bitte geben Sie dies immer an, wenn Sie fragen. Vielen Dank.
Slhck

3
Woher hast du -strict 2? Einfach nur neugierig , wie es ist nicht in der Dokumentation: ffmpeg.org/ffmpeg.html
StackOverflowed

Es ist für die Qualität nach der Installation von ffmpeg. In der ffmpeg-Hilfe finden Sie diese Option
Kalai


1
Ich denke, das Problem hier war eigentlich nur die Tatsache, dass Sie das von und vor dem -i movie.mp4 setzen. Argumente für diesen Stream gehen danach, oder? Deshalb hat der andere Weg funktioniert. = /
Brent Rittenhouse

Antworten:


573

Sie haben wahrscheinlich keinen Keyframe an der 3-Sekunden-Marke. Da Nicht-Keyframes Unterschiede zu anderen Frames codieren, benötigen sie alle Daten, beginnend mit dem vorherigen Keyframe.

Mit dem mp4-Container ist es möglich, einen Nicht-Keyframe zu schneiden, ohne ihn mithilfe einer Bearbeitungsliste neu zu codieren. Mit anderen Worten, wenn der nächste Keyframe vor 3s bei 0s liegt, wird das Video ab 0s kopiert und der Player mithilfe einer Bearbeitungsliste angewiesen, 3 Sekunden später mit dem Spielen zu beginnen.

Wenn Sie das neueste ffmpeg von git master verwenden, wird dies mithilfe einer Bearbeitungsliste durchgeführt, wenn Sie mit dem von Ihnen angegebenen Befehl aufgerufen werden. Wenn dies bei Ihnen nicht funktioniert, verwenden Sie wahrscheinlich entweder eine ältere Version von ffmpeg oder Ihr Player unterstützt keine Bearbeitungslisten. Einige Player ignorieren die Bearbeitungsliste und spielen immer alle Medien in der Datei von Anfang bis Ende ab.

Wenn Sie genau ab einem Nicht-Keyframe schneiden möchten und es ab dem gewünschten Punkt auf einem Player abspielen möchten, der keine Bearbeitungslisten unterstützt, oder sicherstellen möchten, dass sich der ausgeschnittene Teil nicht tatsächlich in der Ausgabedatei befindet (z. B.) Wenn es vertrauliche Informationen enthält, können Sie dies tun, indem Sie neu codieren, sodass genau zum gewünschten Startzeitpunkt ein Keyframe vorhanden ist. Die Neucodierung ist die Standardeinstellung, wenn Sie nichts angeben copy. Zum Beispiel:

ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4

Bei der Neucodierung möchten Sie möglicherweise auch zusätzliche qualitätsbezogene Optionen oder einen bestimmten AAC-Encoder hinzufügen. Weitere Informationen finden Sie im x264-Codierungshandbuch von ffmpeg für Video und im AAC-Codierungshandbuch für Audio.

Außerdem gibt die -tOption eine Dauer und keine Endzeit an. Der obige Befehl codiert 8 Sekunden Video ab 3 Sekunden. Um bei 3s zu beginnen und bei 8s zu enden, verwenden Sie -t 5. Wenn Sie eine aktuelle Version von ffmpeg verwenden Sie auch ersetzen können -tmit -toin dem obigen Befehl zu Ende zu der angegebenen Zeit.


4
Gibt es eine Verknüpfung, die bis zum Ende des Videos angegeben werden muss?
Jikku Jose

20
@JikkuJose: Lassen Sie das -t/ -tound sein Argument weg , um bis zum Ende fortzufahren.
Mark4o

41
Hinweis: Es ist schneller, -ssVOR der Eingabedatei (vorher -i) zu liefern , da ffmpeg auf diese Weise direkt zum Speicherort springt. Dadurch wird jedoch auch die Zeit "Null" für diesen Ort festgelegt, was bedeutet, dass -toauf die falsche Zeit verwiesen wird. Quelle: trac.ffmpeg.org/wiki/Seeking
Denilson Sá Maia

4
Nachdem ich dies verwendet habe ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 cut.mp4, tritt ein Problem mit der Audio- und Videosynchronisierung auf , obwohl die Originaldatei kein solches Problem aufweist.
user2002522

6
@ user2002522: Versuchen Sie es ohne -async 1.
Mark4o

431

Versuchen Sie dies zu verwenden. Es ist der schnellste und beste ffmpeg-Weg, den ich herausgefunden habe:

 ffmpeg -ss 00:01:00 -i input.mp4 -to 00:02:00 -c copy output.mp4

Dieser Befehl schneidet Ihr Video in Sekunden!

Ich habe es in meinem Blog hier erklärt :

-i: Dies gibt die Eingabedatei an. In diesem Fall ist es (input.mp4).
-ss: Wird mit -i verwendet, sucht dies in der Eingabedatei (input.mp4) nach Position.
00:01:00: Dies ist die Zeit, mit der Ihr zugeschnittenes Video beginnt.
-to: Dies gibt die Dauer von Anfang (00:01:40) bis Ende (00:02:12) an.
00:02:00: Dies ist die Zeit, mit der Ihr zugeschnittenes Video endet.
-c copy: Dies ist eine Option zum Trimmen per Stream-Kopie. (NB: Sehr schnell)

Das Timing-Format lautet: hh: mm: ss

Bitte beachten Sie, dass die derzeit hoch bewertete Antwort veraltet ist und das Trimmen extrem langsam wäre. Weitere Informationen finden Sie in diesem offiziellen ffmpeg- Artikel .


9
Dies verarbeitete meine 45 min 720p-Datei in 3s. Dies sollte die richtige Antwort sein.
Dheeraj Bhaskar

7
Möglicherweise leiden Sie jedoch immer noch unter einem Mangel an Keyframes. Ich habe Ihren Ansatz zum Schneiden gewählt und dann gemäß der akzeptierten Antwort neu codiert, um sicherzustellen, dass ich den Zeitaufwand für das Neucodieren minimiert habe.
Pelson

7
Wie @pelson sagt, werden dadurch Keyframes abgeschnitten und die ersten Sekunden leer gelassen (wenn die Schnittzeit zwischen Keyframes liegt). Interessanterweise löst das Ändern der Parameterreihenfolge das Problem : ffmpeg -ss 00:01:00 -to 00:02:00 -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4. Jetzt ist das Überspringen jedoch unterbrochen und die Endzeit ist nicht korrekt (in meinem Fall).
Raphael

6
Sie sollten diese Antwort verwenden, wenn Sie nicht auf eine exakte Millisekunde zuschneiden müssen, um den nächstgelegenen verfügbaren Keyframe auszuwählen. Deshalb ist es so schnell, dass es die nächstgelegenen Keyframes auswählt und das Snippet herausnimmt, ohne dass eine Neucodierung erforderlich ist. Wenn Sie jedoch eine genaue Zeit benötigen, reicht es nicht aus, den nächsten Keyframe zu verwenden, da dieser mit Sicherheit nicht genau übereinstimmt. Die einzige verfügbare Lösung besteht darin, das Video neu zu codieren. Deshalb ist es so langsam. Dies ist jedoch die einzige Lösung, wenn Sie dies benötigen. Deshalb sollte die andere Antwort die akzeptierte sein, denn darum ging es bei OP.
Yamaneko

4
Ich weiß nicht warum, aber dies scheint nicht korrekter zu sein als die akzeptierte Antwort, da dies zu Problemen mit fehlenden Schlüsselbildern führt. Bei kurzen Videoclips ist der Effekt nicht akzeptabel. In solchen Fällen scheint ein langsamer Reencode die einzige Lösung zu sein.
icarus74

91
ffmpeg -i movie.mp4 -ss 00:00:03 -t 00:00:08 -async 1 -c copy cut.mp4 

Verwenden Sie -c copy, um sofort zu erstellen. In diesem Fall wird ffmpeg das Video nicht neu codieren, sondern nur auf die entsprechende Größe zuschneiden.


2
von -c Kopie funktioniert gut, aber nur, wenn ich -async 1
dorien

2
Dies führt beim Schreiben zu einem Fehler aufgrund ungültiger Header bei unterschiedlichen Eingabe- und Ausgabecontainern, z. B. .mkv-Eingabe und .mp4-Ausgabe.
Assil Ksiksi

1
Okay, um .mkv in .mp4 zu konvertieren, müssen Sie einen anderen Befehl verwenden: ffmpeg -i movie.mkv -vcodec copy -acodec copy converted_movie.mp4und umgekehrt
Vlad Hudnitsky

Was sind die Vorteile einer Neucodierung? Ist es von Nutzen, wenn wir nur kleinere Videos im gleichen Format wollen?
Harsha

29
    ffmpeg -i movie.mp4 -vf trim=3:8 cut.mp4

Lass alles außer von Sekunde 3 bis Sekunde 8 fallen.


4
Ich bekomme die ersten 8 Sekunden damit, wobei die ersten 3 Sekunden im ersten Frame eingefroren sind. Wird durch Verketten des setpts=PTS-STARTPTSFilters nach dem Trimmfilter behoben.
Jiggunjer

Hier steht "Der Encoder 'aac' ist experimentell, aber experimentelle Codecs sind nicht aktiviert. Fügen Sie '-strict -2' hinzu, wenn Sie ihn verwenden möchten." Das Hinzufügen von -strict -2 hilft nicht. Das Ergebnis ist eine Datei mit der Länge Null.
Ivan

4
@Ivan, haben Sie versucht, das Hinzufügen -strict -2vor cut.mp4(im Gegensatz zu dem Ende der Befehlszeile im Gegensatz)?
Jan Gondol

Hey, kannst du mir sagen, ob ich nur Videos ohne 3 bis 8 Sekunden will?
Parth Solanki

1
Dies ist super langsam
Tessaracter

21

Geben Sie die Endzeit als Eingabeoption und die Startzeit als Ausgabeoption an, um basierend auf der Start- und Endzeit des Quellvideos zu schneiden und keine Berechnungen durchführen zu müssen .

ffmpeg -t 1:00 -i input.mpg -ss 45 output.mpg

Dies ergibt einen 15-Sekunden-Schnitt von 0:45 bis 1:00.

Dies liegt daran -ss, dass die verworfene Zeit, wenn sie als Ausgabeoption angegeben wird, immer noch in der Gesamtzeit enthalten ist, die von der Eingabe gelesen wird, um -tzu wissen, wann zu stoppen ist. Wenn -ssals Eingabemöglichkeit angegeben wird , wird die Startzeit gesucht und nicht gezählt , weshalb die Verwirrung entsteht.

Es ist langsamer als das Suchen, da das ausgelassene Segment noch verarbeitet wird, bevor es verworfen wird, aber dies ist meines Wissens die einzige Möglichkeit, dies zu tun. Wenn Sie aus einer großen Datei herausschneiden, ist es vorsichtiger, nur zu rechnen und -ssfür die Eingabe zu verwenden.


4
langsam, aber das einzige, was für mich funktioniert hat (ohne Frames aus anderen Antworten zu verlieren)
techkuz

8

Folgendes verwende ich:

ffmpeg -i input.mkv -ss 00:01:00 -to 00:02:00 -c:v copy -c:a copy output.mp4

Generierte mp4Dateien können auch in verwendet werden iMovie.

Referenz: https://www.arj.no/2018/05/18/trimvideo


Wenn Sie mehrere Schnittszenen verketten möchten, können Sie das folgende Skript verwenden:

#!/usr/bin/env python3

import subprocess

name = "batman.mp4"

times = []
times.append(["01:06:00", "01:07:00"])
times.append(["01:08:00", "01:09:00"])

open('concatenate.txt', 'w').close()
for idx, time in enumerate(times):
    output_filename = f"output{idx}.mp4"
    cmd = ["ffmpeg", "-i", name, "-ss", time[0], "-to", time[1], "-c:v", "copy", "-c:a", "copy", output_filename]
    subprocess.check_output(cmd)
    with open("concatenate.txt", "a") as myfile:
        myfile.write(f"file {output_filename}\n")

cmd = ["ffmpeg", "-f", "concat", "-i", "concatenate.txt", "-c", "copy", "final.mp4"]
output = subprocess.check_output(cmd).decode("utf-8").strip()

Dies wurde jedoch bereits beantwortet
Tessaracter

1
Mein Ansatz unterscheidet sich von den akzeptierten Antworten. Ich habe diejenigen ausprobiert, die länger Zeit haben, um die mp4-Datei zu erstellen. @ Tessaracter
Alper

1
Dies ist die EINZIGE Antwort hier, die für mich beim Ausschneiden eines kleinen Clips aus einem großen Video funktioniert hat. Das funktioniert und SCHNELL !!! Vielen Dank
lacostenycoder

1
Gern geschehen, ich bin froh, dass ich helfen kann. Ich konnte diese Antwort finden, nachdem ich viele Ansätze ausprobiert hatte. Die meisten von ihnen waren ziemlich langsam. @lacostenycoder
alper

Könnte dies nicht einfach "-c" mit "copy" verwenden, anstatt -c: v und -c: a aufzuteilen?
Nstenz


-3

Obwohl ich 6 Jahre zu spät bin, denke ich, dass alle obigen Antworten die Frage, die @kalai stellt, nicht richtig beantwortet haben . Das folgende Bash-Skript verarbeitet eine Textdatei im folgenden Format:

URL | start_time | end_time | filename

zum Beispiel

https://www.youtube.com/watch?v=iUDURCrvrMI|00:02:02|00:03:41|1

und durchlaufen Sie die Datei, laden Sie die youtube-dlunterstützte Datei herunter , berechnen Sie die Dauer zwischen start_timeund end_timeund übergeben Sie sie an ffmpeg, da -tes sich tatsächlich um die Dauer handelt , nicht um die tatsächlicheend_time

Schlagen Sie mich, wenn Sie Fragen haben.

    for i in $(<video.txt);
    do
        URL=`echo $i | cut -d "|" -f 1`;
        START=`echo $i | cut -d "|" -f 2`;
        END=`echo $i | cut -d "|" -f 3`;
        FILE=`echo $i | cut -d "|" -f 4`;

        SEC1=`echo $START | sed 's/^/((/; s/:/)*60+/g' | bc`
        SEC2=`echo $END | sed 's/^/((/; s/:/)*60+/g' | bc`

        DIFFSEC=`expr ${SEC2} - ${SEC1}`

        ffmpeg $(youtube-dl -g $URL | sed "s/.*/-ss $START -i &/") -t $DIFFSEC -c copy $FILE".mkv";
        ffmpeg -i $FILE".mkv" -f mp3 -ab 192000 -vn $FILE".mp3";
        rm $FILE".mkv";
    done;

Dies gibt nur eine MP3-Audiodatei und KEIN Video aus.
Lacostenycoder

Ja ... ändere einfach das Ausgabeformat.
Rolodex
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.