Wenn Sie CPU-Zyklen übrig haben, können Sie parallel aus mehreren Videos extrahieren:parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Ole Tange
Antworten:
155
Wenn der JPEG-Codierungsschritt zu leistungsintensiv ist, können Sie die unkomprimierten Frames jederzeit als BMP-Bilder speichern:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Dies hat auch den Vorteil, dass durch Quantisierung durch Transcodierung in JPEG kein weiterer Qualitätsverlust entsteht. (PNG ist ebenfalls verlustfrei, die Codierung dauert jedoch in der Regel viel länger als die von JPEG.)
Dies führt dazu, dass viel Frame auf meine Maschine fällt. Kann ich ffmpeg anweisen, alles zu rendern?
Evi1M4chine
45
@ Evi1M4chine entfernen Sie einfach den -r-Parameter, um alle Frames zu extrahieren
studioj
14
Ich möchte hinzufügen, dass JPEG zwar die CPU nicht wirklich belastet, unkomprimierte Bitmaps den Speicher jedoch sehr stark belasten. Ich bezweifle, dass Sie mit BMP im Vergleich zu JPEG einen höheren Durchsatz erzielen.
Marcus Müller
4
So extrahieren Sie alle Frames:ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
Fiatjaf
10
Du meinst ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png, richtig? (Sie haben das verpasst -i)
Joschua
68
Kam über diese Frage, also hier ein kurzer Vergleich. Vergleichen Sie diese beiden Möglichkeiten, um ein Bild pro Minute aus einem 38 m07 langen Video zu extrahieren:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1m36.029s
Dies dauert lange, da ffmpeg die gesamte Videodatei analysiert, um die gewünschten Frames zu erhalten.
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0m4.689s
Das ist ungefähr 20 mal schneller. Wir verwenden die schnelle Suche, um zum gewünschten Zeitindex zu gelangen und einen Frame zu extrahieren, und rufen dann für jeden Zeitindex mehrmals ffmpeg auf. Beachten Sie, dass dies -accurate_seekdie Standardeinstellung ist
, und stellen Sie sicher, dass Sie -ssvor der Eingabevideooption hinzufügen -i.
Beachten Sie, dass es besser ist , zu verwenden , -filter:v -fps=fps=...anstatt -rwie diese ungenau sein können. Obwohl das Ticket als fest markiert ist , sind dennoch einige Probleme aufgetreten. Gehen Sie also besser auf Nummer sicher.
bcist kein natives Ubuntu-Paket, stattdessen kann man bash verwenden : let "i = $i * 60". Übrigens - ausgezeichnete Idee
Gilad Mayani
3
Guter Tipp Zugabe -ssvor -i. Andernfalls wird das gesamte Video dekodiert und die nicht erforderlichen Frames werden verworfen
MoustafaAAtta
2
Da dies die Spitze von Google ist, möchte ich darauf hinweisen, dass dies auch 2018 ein Ansatz ist, der Dividenden bringt. Das beste Ergebnis scheint darin zu bestehen, einen ffmpegpro Kern Ihres Hosts auszuführen - was (für bmp) zu nahezu linearen Geschwindigkeitsverbesserungen führt (bis Sie auf einen anderen Engpass wie die Festplatte stoßen).
Knetic
Dies sollte die akzeptierte Antwort sein, da es sich bei der Frage um den schnellsten Weg handelt. Natürlich müssen Sie die Exit-Variable für die 'for-Schleife' mit ffprobe kennen, was meiner Meinung nach im Vergleich zu den anderen Methoden immer noch schneller ist.
iamprem
9
Wenn Sie genau wissen, welche Frames extrahiert werden sollen, z. B. 1, 200, 400, 600, 800, 1000, versuchen Sie Folgendes:
Ich verwende dies mit einer Pipe zu Imagemagicks Montage, um eine Vorschau von 10 Bildern von Videos zu erhalten. Offensichtlich die Rahmennummern, die Sie mit herausfinden müssenffprobe
Ich versuche, ffmpeg -i "input URL" -vf fps=1/5 out%d.png wo die Eingabe-URL ein https-Link sein muss.
x2212
ffmpeg -i file.mpg -vf fps=1 %d.jpg
Kishan Vaghela
1
In meinem Fall brauche ich mindestens jede Sekunde Frames. Ich habe oben den Ansatz "Suchen nach" verwendet, mich aber gefragt, ob ich die Aufgabe parallelisieren könnte. Ich habe hier die N-Prozesse mit FIFO-Ansatz verwendet:
/unix/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
Im Wesentlichen habe ich den Prozess mit & gegabelt, aber die Anzahl der gleichzeitigen Threads auf N begrenzt.
Dies verbesserte in meinem Fall den Suchansatz von 26 Sekunden auf 16 Sekunden. Das einzige Problem ist, dass der Haupt-Thread nicht sauber zum Terminal zurückkehrt, da stdout überflutet wird.
parallel -i {} -r 1/1 {.}-%03d.bmp ::: *mpg
Antworten:
Wenn der JPEG-Codierungsschritt zu leistungsintensiv ist, können Sie die unkomprimierten Frames jederzeit als BMP-Bilder speichern:
Dies hat auch den Vorteil, dass durch Quantisierung durch Transcodierung in JPEG kein weiterer Qualitätsverlust entsteht. (PNG ist ebenfalls verlustfrei, die Codierung dauert jedoch in der Regel viel länger als die von JPEG.)
quelle
ffmpeg -r 1 file.mp4 -r 1 "$filename%03d.png"
ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png
, richtig? (Sie haben das verpasst-i
)Kam über diese Frage, also hier ein kurzer Vergleich. Vergleichen Sie diese beiden Möglichkeiten, um ein Bild pro Minute aus einem 38 m07 langen Video zu extrahieren:
1m36.029s
Dies dauert lange, da ffmpeg die gesamte Videodatei analysiert, um die gewünschten Frames zu erhalten.
0m4.689s
Das ist ungefähr 20 mal schneller. Wir verwenden die schnelle Suche, um zum gewünschten Zeitindex zu gelangen und einen Frame zu extrahieren, und rufen dann für jeden Zeitindex mehrmals ffmpeg auf. Beachten Sie, dass dies
-accurate_seek
die Standardeinstellung ist , und stellen Sie sicher, dass Sie-ss
vor der Eingabevideooption hinzufügen-i
.Beachten Sie, dass es besser ist , zu verwenden ,
-filter:v -fps=fps=...
anstatt-r
wie diese ungenau sein können. Obwohl das Ticket als fest markiert ist , sind dennoch einige Probleme aufgetreten. Gehen Sie also besser auf Nummer sicher.quelle
bc
ist kein natives Ubuntu-Paket, stattdessen kann man bash verwenden :let "i = $i * 60"
. Übrigens - ausgezeichnete Idee-ss
vor-i
. Andernfalls wird das gesamte Video dekodiert und die nicht erforderlichen Frames werden verworfenffmpeg
pro Kern Ihres Hosts auszuführen - was (für bmp) zu nahezu linearen Geschwindigkeitsverbesserungen führt (bis Sie auf einen anderen Engpass wie die Festplatte stoßen).Wenn Sie genau wissen, welche Frames extrahiert werden sollen, z. B. 1, 200, 400, 600, 800, 1000, versuchen Sie Folgendes:
Ich verwende dies mit einer Pipe zu Imagemagicks Montage, um eine Vorschau von 10 Bildern von Videos zu erhalten. Offensichtlich die Rahmennummern, die Sie mit herausfinden müssen
ffprobe
.
Kleine Erklärung:
+
für OR und*
für AND\,
entkommt einfach dem,
Charakter-vsync vfr -q:v 2
es scheint nicht zu funktionieren, aber ich weiß nicht warum - jemand?quelle
Ich versuchte es. 3600 Frame in 32 Sekunden. Ihre Methode ist sehr langsam. Sie sollten dies versuchen.
quelle
ffmpeg -i "input URL" -vf fps=1/5 out%d.png
wo die Eingabe-URL ein https-Link sein muss.ffmpeg -i file.mpg -vf fps=1 %d.jpg
In meinem Fall brauche ich mindestens jede Sekunde Frames. Ich habe oben den Ansatz "Suchen nach" verwendet, mich aber gefragt, ob ich die Aufgabe parallelisieren könnte. Ich habe hier die N-Prozesse mit FIFO-Ansatz verwendet: /unix/103920/parallelize-a-bash-for-loop/216475#216475
Im Wesentlichen habe ich den Prozess mit & gegabelt, aber die Anzahl der gleichzeitigen Threads auf N begrenzt.
Dies verbesserte in meinem Fall den Suchansatz von 26 Sekunden auf 16 Sekunden. Das einzige Problem ist, dass der Haupt-Thread nicht sauber zum Terminal zurückkehrt, da stdout überflutet wird.
quelle
Das hat bei mir funktioniert
ffmpeg -i file.mp4 -vf fps=1 %d.jpg
quelle