ffmpeg extrahiert Bilder von mehreren ausgewählten Zeitpunkten

871
Jakob Winter

Ich habe ein Videofilm und möchte ein einzelnes Bild aus (etwa 1500) bestimmten Zeitpunkten extrahieren (expl. -Ss 00:50, ss 00:67, ss: 01:70 ...)

Gibt es eine Möglichkeit, dies zu tun? Ich habe versucht, diesen Befehl zu verwenden:

ffmpeg.exe -ss 00:50 -i all.avi -t 00:00:01 -vframes 1 images-filename_%03d.png 

Dies funktioniert großartig für ein einzelnes Bild, aber gibt es eine Möglichkeit, dies für so viele bestimmte Zeitpunkte zu tun?

Hat jemand einen Rat?

1

2 Antworten auf die Frage

1
slhck

Fügen Sie mehrere Zeitstempel als Optionen für den selectFilter hinzu.

ffmpeg -i input.mp4 -filter:v \ "select='eq(t\,1.5)+eq(t\,10)+eq(t\,20)'" \ -vsync drop images-filename_%03d.png 

Wenn der Filter den Wert true hat, gibt er einen Frame aus. Durch das Hinzufügen von Überprüfungen, bei denen der Frame-Zeitstempel tmit einem bestimmten Zeitstempel in Sekunden (z. B. 1.5) verglichen wird, erhalten Sie alle Frames zu diesen Zeitstempeln.

Ich habe eine [verbesserte Version] (https://superuser.com/a/1330042/598963) dieser Antwort hinzugefügt. Leon vor 6 Jahren 0
Interessanter Ansatz! Hatte in den letzten Jahren nicht viel mit fraktionalen Frameraten gearbeitet, aber sie verursachen viele Probleme. slhck vor 6 Jahren 0
1
Leon

Diese Antwort verbessert auf @slhck ‚s Antwort, die in einigen Situationen kann nicht funktionieren.

Bei der Auswahl von Frames nach (ungefährem) Zeitstempel kann es vorkommen, dass der tatsächliche Zeitstempel des Frames nicht exakt mit dem gewünschten Zeitstempel übereinstimmt. In einem Video mit einer Bildrate von 23,98 (24000/1001) gibt es beispielsweise keinen Frame mit Zeitstempel 1.0 - der nächste Frame hat einen Zeitstempelwert von 1.001.

Der Ausdruck wird eq(t, specific_timepoint)nur dann tals wahr ausgewertet, wenn er genau gleich ist specific_timepoint. Daher kann in der oben beschriebenen Situation kein Rahmen ausgewählt werden. Als Workaround können wir den ersten Frame unmittelbar nach dem gewünschten Zeitstempel auswählen, dh den Frame, dessen Timestamp-Wert größer oder gleich dem angegebenen Zeitpunkt ist, während der Zeitstempel des vorhergehenden Frames niedriger als der angegebene Zeitpunkt war. Der Auswahlausdruck für einen einzelnen Zeitpunkt lautet

lt(prev_pts * TB,timepoint) * gte(pts * TB,timepoint)

Beachten Sie, dass ich bewusst keine kürzere Variante verwendet habe

between(timepoint, prev_pts*TB, pts*TB)

das ist äquivalent zu

lte(prev_pts * TB,timepoint) * gte(pts * TB,timepoint)

B. zwei aufeinanderfolgende Frames auswählen, wenn der Zeitstempelwert von (dem ersten) einen genau mit dem angegebenen Zeitpunktwert übereinstimmt.

Beispiel: Auswählen der Bilder, die den Zeitpunkten 1.5, 10 und 20 entsprechen oder unmittelbar darauf folgen:

ffmpeg -i input.mp4 -filter:v \ "select='lt(prev_pts*TB\,1.5)*gte(pts*TB\,1.5) \ +lt(prev_pts*TB\,10)*gte(pts*TB\,10) \ +lt(prev_pts*TB\,20)*gte(pts*TB\,20)'" \ -vsync drop images-filename_%03d.png