Wie kann man mit FFmpeg Videos basierend auf Zeitstempeln aus CSV beschleunigen?

Wie kann man mit FFmpeg Videos basierend auf Zeitstempeln aus CSV beschleunigen?

Es gibt bereits Fragen zur Beschleunigung eines Videos mit FFmpeg, wieDieses hier.

Meine Frage ist: Gibt es auch eine Möglichkeit, mehrere Abschnitte anzugeben, die über eine externe CSV beschleunigt werden sollen?

Meine CSV sieht folgendermaßen aus:

start, end
00:00:03.296, 00:00:14.372,
00:00:16.388, 00:00:33.635,
00:00:33.693, 00:00:39.428,
00:00:39.460, 00:00:50.355,
00:00:50.355, 00:01:17.892,
00:01:17.892, 00:01:19.845,
00:01:19.845, 00:01:47.616,

Dies sind die genauen Abschnitte (ein Abschnitt pro Zeile, zwei Zeitstempel, die den Anfang und das Ende jedes Abschnitts definieren), die um das Zehnfache beschleunigt werden sollen. Der Rest soll die ursprüngliche Wiedergabegeschwindigkeit beibehalten.

Gibt es eine Möglichkeit, dies zu tun?

Antwort1

Wir können den gewünschten PTS-Zeitstempel für jedes Videobild festlegen, indem wirsetztFilter mit ausführlichem verschachteltem ifAusdruck.

Die folgende Antwort ist nur ein „Proof of Concept“, vorausgesetzt, Sie verfügen über das Wissen, um den komplexeren Ausdruck, den Sie benötigen, programmgesteuert zu erstellen. Die Lösung geht davon aus, dass das Eingabevideo eine feste Bildrate hat und dass es einfach ist, den Eingabezeitstempel aus der Eingabebildnummer zu berechnen.

Hinweis:
Durch das Beschleunigen von Teilen des Videos durch Festlegen der Zeitstempel wird ein Video mit variabler Bildrate (VFR) erstellt, das möglicherweise nicht auf allen Videoplayern gut wiedergegeben wird.
Es ist möglicherweise besser, ein Video mit fester Bildrate zu erstellen, indem Sie das gesamte Video um den Faktor 10 beschleunigen und jedes Bild 10 Mal in den Teilen der Originalrate duplizieren.
Beachten Sie, dass es relativ einfach ist, die Bilder mit einem Python-Skript zu duplizieren, das Bilder mit OpenCV liest und mit OpenCV schreibt (oder besser an FFmpeg weiterleitet).


Angenommen, wir haben die folgende Eingabedatei (40 Frames bei 1fps):

ffmpeg -y -f lavfi -i testsrc=size=192x108:rate=1:duration=40 -c:v libx264 -g 1 input.mp4

Die Zeitstempel des Eingabevideos sind:

 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,

Angenommen, wir möchten im Bereich [0, 19] und [30, 39] beschleunigen und die folgenden Ausgabezeitstempel erhalten:

 0,    1,    2,    3,    4,    5,    6,    7,    8,    9,
10, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9,
11,   12,   13,   14,   15,   16,   17,   18,   19,   20,
21, 21.1, 21.2, 21.3, 21.4, 21.5, 21.6, 21.7, 21.8, 21.9,

Wir können den folgenden FFmpeg-Befehl verwenden:

ffmpeg -y -r 100 -i input.mp4 -fps_mode:v passthrough -vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'" -c:v libx264 -g 1 output.mp4

  • -r 100wird verwendet, um die Paketdauer auf 10 ms einzustellen (eine kurze Paketdauer ermöglicht eine höhere Auflösung der Zeitstempel).
  • -fps_mode:v passthrough- übergibt jedes Eingabebild vom Eingang an den Ausgang (ohne die Bilder aufgrund der Rate von 100 fps zu duplizieren).
  • -vf "setpts='(if(lt(N,10), N, if(lt(N,20), ((N-10)/10)+10, if(lt(N,30), 11+(N-20), 21+(N-30)/10))))/TB'"- Verwendet ifAusdrücke und etwas Mathematik zum Anpassen der Zeitstempel.
    Der ifAusdruck gilt, wenn (Bedingung, Wert wenn wahr, Wert wenn falsch).
    Nist die Nummer des Eingabebilds, beginnen Sie bei Null zu zählen. setzt PTS für die ersten 10 Bilder
    if(lt(N,10), N, ...auf ... dividiert durch die Zeit in Sekunden durch die Zeitbasis.N
    /TB
  • -g 1- Setzen Sie die GOP-Größe zum Testen auf 1 (entfernen Sie sie). Dadurch bleibt das PTS bei Verwendung von FFprobe sortiert.

Überprüfen der Ausgabezeitstempel mit FFprobe:
ffprobe -select_streams v:0 -of default=noprint_wrappers=1 -show_entries packet=pts_time output.mp4

Die Ausgabe ist wie erwartet:

pts_time=0.000000
pts_time=1.000000
pts_time=2.000000
pts_time=3.000000
pts_time=4.000000
pts_time=5.000000
pts_time=6.000000
pts_time=7.000000
pts_time=8.000000
pts_time=9.000000
pts_time=10.000000
pts_time=10.100000
pts_time=10.190000
pts_time=10.300000
pts_time=10.400000
pts_time=10.500000
pts_time=10.600000
pts_time=10.700000
pts_time=10.800000
pts_time=10.900000
pts_time=11.000000
pts_time=12.000000
pts_time=13.000000
pts_time=14.000000
pts_time=15.000000
pts_time=16.000000
pts_time=17.000000
pts_time=18.000000
pts_time=19.000000
pts_time=20.000000
pts_time=21.000000
pts_time=21.100000
pts_time=21.200000
pts_time=21.300000
pts_time=21.400000
pts_time=21.500000
pts_time=21.600000
pts_time=21.700000
pts_time=21.800000
pts_time=21.900000

Animiertes GIF, das die Ausgabe demonstriert:
Bildbeschreibung hier eingeben
(Erstellt mit ffmpeg -y -i output.mp4 -filter_complex "[0:v]split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -r 1 output.gif)

verwandte Informationen