Schneiden Sie Videodateien präzise von der Befehlszeile aus

22

Ich habe Probleme, eine CLI-Anwendung zu finden, die eine Videodatei (vorzugsweise AVI, MKV und MP4) aufnimmt und sehr kurze Clips (2-6 Sekunden) zeitgenau ausschneidet. Ich habe ffmpeg , mencoder , avidemux und mp4box ausprobiert , aber alle schneiden auf Keyframes, wodurch Clips mit einer Länge von mehr als 6 Sekunden erstellt werden. Gibt es ein Tool, das die Eingabedatei neu codiert und die genaue Zeit schneidet oder ungenau schneidet, neu codiert und dann genau schneidet?

curmil
quelle
Sie müssen wahrscheinlich vor dem Schneiden neu codieren, um es richtig zu machen. Sie könnten die Dinge wahrscheinlich beschleunigen, indem Sie zuerst die umliegenden Keyframes ausschneiden und nur die Snippets neu codieren.
Nifle
4
Welchen FFmpeg-Befehl haben Sie genau ausprobiert? Ich glaube, wenn du das Video vorher dekodierst (dh den -ssParameter nachher platzierst -i ), sollte es genauer sein.
Slhck
1
Der FFmpeg-Trick hat funktioniert! Mir war nicht klar, dass die Bestellung so wichtig war. Ist dies für alle anderen Tools gleich?
Curmil

Antworten:

23

Video schneiden mit ffmpeg

Mit FFmpeg können Sie Videos präzise schneiden. Seit Version 2.5 ist es sehr einfach. Dies würde beispielsweise 10 Sekunden ab 0 Minuten, 3 Sekunden und 123 Millisekunden verkürzen.

ffmpeg -ss 00:00:03.123 -i input.mp4 -t 10 -c:v libx264 -c:a copy out.mp4

Die Position und die Zeit können entweder in Sekunden oder in hh:mm:ss[.xxx]Form sein.

Beachten Sie, dass in diesen Beispielen das Video mit dem x264- Encoder neu codiert wird . Audio wird kopiert.

Sie können -toanstelle von auch -tden Endpunkt anstelle der Dauer angeben. In diesem Fall jedoch -toist äquivalent zu -t, da durch die Umsetzung -ssvor -i, wird ffmpeg zuerst zu diesem Punkt suchen und starten Sie dann Ausgabe.

Siehe auch den Seeking- Wiki-Eintrag.


Genaues Schneiden für ältere ffmpegVersionen

Wenn Sie eine ältere Version von ffmpeg haben, müssen Sie für eine genaue Suche das -ssAfter einfügen, -iwas den Kodierungsprozess etwas verlangsamt, da das gesamte Video zuerst dekodiert werden muss:

ffmpeg -i input.mp4 -ss 00:00:03.123 -t 10 -c:v libx264 -c:a copy out.mp4

Hier -tound -tanders verhalten. -t 10Erstellt einen zehn Sekunden langen Clip, während -to 10ein sieben Sekunden langer Clip erstellt wird.

slhck
quelle
Anstelle von -c:v libx264 -c:a libfaacich denke, wir können mit -acodec copy -vcodec copydem Befehl ffmpeg nur die gleichen Codecs wie die Originaldatei erkennen und verwenden. Kann das jemand bestätigen?
Baodad,
2
@Baodad Du kannst, aber das wird nicht genau schneiden. Beim Kopieren von Video- / Audio-Bitstreams muss ffmpeg an einem Keyframe beginnen, der möglicherweise nur jede Sekunde oder noch weiter voneinander entfernt ist.
Slhck
Wie kann man den Fehler "Unknown encoder 'libfaac'" beheben?
Doug
@Doug Wählen Sie beispielsweise einen anderen Encoder -c:a aac -strict experimental. Das ist die einfachste Lösung.
Slhck
1

Das einzige Linux-Kommandozeilen-Tool, das ich bisher gefunden habe und das bildgenau (oder bildgenau) schneiden kann, ist melt( sudo apt-get install melt).

Angenommen, Sie haben eine inputvid.mp4- überprüfen Sie zuerst die Codierungseinstellungen mit say ffmpeg(hier sage ich nur, dass ich sie erneut codieren möchte -f mp4, aber da die Datei /dev/nullso verworfen wird, leite ich stderr um, damit ich sie durchgehen kann - notieren Sie sich in der Mitte yWenn der Befehl dazu auffordert und Sie mit der EINGABETASTE antworten , fährt der Prozess fort und gibt die nützlichen Informationen aus (dies ist mit ffmpeg 3.3.3 unter Ubuntu 14):

ffmpeg -i inputvid.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'
    Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], 389 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 95 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p(progressive), 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

Ok, wir können also eine ffmpegAuswahl libx264und aacEncoder für dieses Video sehen. dann können wir dies eingeben für melt:

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac vcodec=libx264

.... und meltschneidet mit dem Stück zwischen den Frames 7235 und 7349 in eine neue Datei cut.mp4. Um zu überprüfen, ob die cut.mp4Schleifen korrekt sind, geben Sie meltsie noch einmal zweimal wieder - und spielen Sie sie in einem SDL-Fenster ab:

melt cut.mp4 cut.mp4 -consumer sdl

... und hier ist was ffmpegfür diese Datei zu sehen:

ffmpeg -i cut.mp4 -f mp4 /dev/null 2>&1 | grep 'Stream\|encoder'    encoder         : Lavf54.20.4
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 526 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 182 kb/s (default)
y
File '/dev/null' already exists. Overwrite ? [y/N] Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
    encoder         : Lavf57.71.100
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=-1--1, 23.98 fps, 24k tbn, 23.98 tbc (default)
      encoder         : Lavc57.89.100 libx264
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 48000 Hz, stereo, fltp, 128 kb/s (default)
      encoder         : Lavc57.89.100 aac

Die Einstellungen für cut.mp4die Videokodierung scheinen mit inputvid.mp4Ausnahme der Änderung der Videobitrate von 389 kb / s auf 526 kb / s identisch zu sein , und auch die Einstellungen für die Audiokodierung sind nahezu identisch, außer dass die Abtastrate von 44100 auf 48000 Hz geändert wurde. das kann man aber regeln mit:

melt inputvid.mp4 in=7235 out=7349 -consumer avformat:cut.mp4 acodec=aac ar=44100 ab=95k vcodec=libx264 vb=389k

... die endgültige Video-Bitrate beträgt für mich jedoch 337 kb / s. Trotzdem sind die Schnitte bei der Wiedergabe in einer Schleife in Ordnung (und das schließt auch Audio ein), also denke ich, dass dies tatsächlich bildgenau ist ...

sdaau
quelle
1
meltkodiert das Video neu und verwendet die darunter liegenden FFmpeg-Bibliotheken. Wenn Sie eine Neucodierung zulassen, kann ffmpeg dieselbe Ausgabe erzeugen.
Gyan
Danke @Gyan - war mir dessen nicht bewusst (vor allem, dass meltFFmpeg-Bibliotheken verwendet), gut zu wissen!
Sdaau
melt sieht einfacher aus als ffmpeg. Wir brauchen nur eine Methode, um Zeiten anzugeben, insbesondere Zeiten in Stunden, Minuten, Sekunden oder Stunden, Minuten, Sekunden und Millisekunden, die sie in den richtigen Frame konvertieren.
Barlop
0

Wie Baodad in den Kommentaren sagte (ich poste, weil es nicht leicht zu finden ist, wenn Sie schnell lesen), ist der bessere Ansatz, die Audio- / Video-Encoder automatisch per ffmpeg zu erkennen, also:

ffmpeg -ss 00:05:17.18 -i in.mp4 -t 00:06:29.10 -acodec copy -vcodec copy out.mp4 
  • Beginnen Sie um 00: 05: 17.18 Uhr
  • Eingabe = in.mp4
  • stop @ 00: 06: 29.10
  • output = out.mp4
Gilles Quenot
quelle
2
Dies kodiert nicht neu und liefert keine Rahmengenauigkeit.
Andrea Lazzarotto