こんにちは、ffmpeg を使用してビデオからフレームを抽出する必要があります。これよりも高速な方法はありますか。
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
JPEG エンコーディングのステップがパフォーマンスに負荷がかかりすぎる場合は、フレームを圧縮せずに BMP 画像として常に保存できます。
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
これには、JPEG へのトランスコードによる量子化による品質低下が発生しないという利点もあります。(PNG もロスレスですが、エンコードに JPEG よりもはるかに時間がかかる傾向があります。)
この質問に出くわしたので、ここで簡単に比較します。長さ 38 分 7 秒のビデオから 1 分あたり 1 フレームを抽出する 2 つの異なる方法を比較してください。
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1分36.029秒
ffmpeg はビデオ ファイル全体を解析して必要なフレームを取得するため、これには時間がかかります。
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
0分4.689秒
これは約 20 倍高速です。高速シークを使用して目的の時間インデックスに移動し、フレームを抽出してから、時間インデックスごとに ffmpeg を数回呼び出します。-accurate_seek
がデフォルトであることに注意してください。-ss
入力ビデオ-i
オプションの前に
必ず追加してください。
後者は不正確な場合があるため、-filter:v -fps=fps=...
代わりに-r
を使用することをお勧めします。チケットは修正済みとマークされていますが、それでもいくつかの問題が発生したため、安全にプレイしてください.
1、200、400、600、800、1000 など、抽出するフレームが正確にわかっている場合は、次を使用してみてください。
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
-vsync vfr -q:v 2
これを Imagemagick のモンタージュへのパイプで使用して、任意のビデオから 10 フレームのプレビューを取得します。明らかに、使用して把握する必要があるフレーム番号ffprobe
ffmpeg -i myVideo.mov -vf \
select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',scale=320:-1 \
-vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
| montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png
.
少し説明:
+
は OR と*
ANDを表します\,
,
単に文字をエスケープしています-vsync vfr -q:v 2
とうまくいかないようですが、理由はわかりません-誰か?