Wie extrahiere ich 1 Screenshot für ein Video mit ffmpeg zu einem bestimmten Zeitpunkt?

109

Es gibt viele Tutorials und Dinge, die zeigen, wie man mit ffmpeg mehrere Screenshots aus einem Video extrahiert. Sie setzen -r und können sogar einen bestimmten Betrag in starten.

Aber ich möchte nur 1 Screenshot bei, sagen wir 01:23:45 in. Oder 1 Screenshot bei 86% in.

Dies ist alles mit ffmpegthumbnailer möglich, aber es ist eine weitere Abhängigkeit, von der ich nicht abhängen möchte. Ich möchte es mit ffmpeg machen können.

Peter Bengtsson
quelle

Antworten:

208

Verwenden Sie die -ssOption:

ffmpeg -ss 01:23:45 -i input -vframes 1 -q:v 2 output.jpg
  • Für die JPEG-Ausgabe verwenden Sie diese Option, um die Ausgabequalität -q:vzu steuern. Der volle Bereich ist eine lineare Skala von 1 bis 31, wobei ein niedrigerer Wert zu einer höheren Qualität führt. 2-5 ist eine gute Auswahl.

  • Der Auswahlfilter bietet eine alternative Methode für komplexere Anforderungen wie die Auswahl nur bestimmter Rahmentypen oder 1 pro 100 usw.

  • Das Platzieren -ssvor der Eingabe erfolgt schneller. Siehe FFmpeg Wiki: Seeking und dieser Auszug aus der ffmpegDokumentation zum CLI-Tool :

-ss Position (Eingabe / Ausgabe)

Bei Verwendung als Eingabeoption (vorher -i) wird in dieser Eingabedatei nach Position gesucht. Beachten Sie, dass es in den meisten Formaten nicht möglich ist, genau zu suchen. Suchen Sie daher ffmpegzum nächstgelegenen Suchpunkt vor der Position. Wenn die Transcodierung -accurate_seekaktiviert ist (Standardeinstellung), wird dieses zusätzliche Segment zwischen Suchpunkt und Position dekodiert und verworfen. Wenn Sie eine Stream-Kopie -noaccurate_seekerstellen oder wenn sie verwendet wird, bleibt sie erhalten.

Bei Verwendung als Ausgabeoption (vor einem Ausgabedateinamen) wird die Eingabe dekodiert, aber verworfen, bis die Zeitstempel die Position erreichen.

Die Position kann entweder in Sekunden oder in hh:mm:ss[.xxx]Form sein.

llogan
quelle
2
Das ist viel schneller. Ich danke dir sehr. Das -ss an die erste Stelle zu setzen, macht einen großen Unterschied.
Peter Bengtsson
Gibt es eine Möglichkeit, den n-ten Frame nach der angegebenen Zeit zu erhalten?
Dorien
@ GuntherPiez Ich sehe nirgendwo eine Erwähnung über mögliche Artefakte.
Stefan Reich
2
Beachten Sie, dass dies vframesin (mindestens) Version 4.2.2 veraltet ist. Per Handbuch "[ vframes] ist ein veralteter Alias ​​für ' -frames:v', den Sie stattdessen verwenden sollten."
Synexis
Funktioniert perfekt und schnell.
Smeterlink
37

FFMpeg kann dies tun, indem es nach dem angegebenen Zeitstempel sucht und genau einen Frame als Bild extrahiert, siehe zum Beispiel:

ffmpeg -i input_file.mp4 -ss 01:23:45 -vframes 1 output.jpg

Lassen Sie uns die Optionen erklären:

-i input file           the path to the input file
-ss 01:23:45            seek the position to the specified timestamp
-vframes 1              only handle one video frame
output.jpg              output filename, should have a well-known extension

Der -ssParameter akzeptiert einen Wert im Formular HH:MM:SS[.xxx]oder als Zahl in Sekunden. Wenn Sie einen Prozentsatz benötigen, müssen Sie die Videodauer im Voraus berechnen.

SirDarius
quelle
Scheint wie erwartet zu funktionieren. Ich vergleiche derzeit, ob dies die gleiche Geschwindigkeit wie die Verwendung von ffmpegthumbnailer ist.
Peter Bengtsson
Ja, dieser Ansatz ist sehr langsam. Siehe peterbe.com/plog/fastest-way-to-take-screencaps-out-of-videos
Peter Bengtsson
7
Versuchen Sie, die Option -ss vor -i zu verwenden, da der Dekodierungsteil der Pipeline übersprungen wird. Dies könnte den Prozess beschleunigen.
SirDarius
1
Gibt es eine Möglichkeit, als PNG anstelle einer Datei in den Stream auszugeben?
Nicke Manarin
1
@NickeManarin Ja .. ffmpeg -ss 01:23:45 -i video.mp4 -c:v png -frames:v 1 image.jpg. Beachten Sie, dass ich auch die -ssOption "Suchen" vor die Eingabedatei in der Befehlszeile setze , wie andere empfohlen haben.
Glenn Slayden