私はビデオファイルを持っていて、(約1500)特定の時点から単一の画像を抽出するのが好きです。(expl.-ss 00:50、ss 00:67、ss:01:70 ...)
これを行う方法はありますか?私はこのコマンドを使おうとしました:
ffmpeg.exe -ss 00:50 -i all.avi -t 00:00:01 -vframes 1 images-filename_%03d.png
これは1つの画像に最適ですが、これほど多くの特定の時点でこれを行う方法はありますか?
誰かアドバイスはありますか?
この回答は @ slhck 's answer を改善しますが、状況によっては機能しない場合があります。
(おおよその)タイムスタンプでフレームを選択する際の微妙な点の1つは、フレームの実際のタイムスタンプが目的のタイムスタンプと正確に等しくない場合があることです。たとえば、フレームレート23.98(24000/1001)のビデオには、タイムスタンプ1.0のフレームはありません。最も近いフレームのタイムスタンプ値は1.001です。
式eq(t, specific_timepoint)
は、t
がspecific_timepoint
と正確に等しい場合にのみtrueと評価されます。したがって、上記の状況ではフレームの選択に失敗します。回避策として、目的のタイムスタンプの直後の最初のフレーム、つまり、タイムスタンプ値が指定された時点以上で、前のフレームのタイムスタンプが指定された時点よりも小さいフレームを選択できます。単一の時点の選択式は次のようになります。
lt(prev_pts * TB,
timepoint
) * gte(pts * TB,
timepoint
)
私は意図的に短いバリアントを使用しなかったことに注意してください
between(
timepoint
, prev_pts*TB, pts*TB)
これは
lte(prev_pts * TB,
timepoint
) * gte(pts * TB,
timepoint
)
(最初の)1つのタイムスタンプ値が指定された時点の値と完全に一致する場合、2つの連続するフレームが選択されるためです。
時点1.5、10、および20に対応する、またはその直後のフレームを選択する例:
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
select
フィルターのオプションとして複数のタイムスタンプを追加します。
ffmpeg -i input.mp4 -filter:v \
"select='eq(t\,1.5)+eq(t\,10)+eq(t\,20)'" \
-vsync drop images-filename_%03d.png
フィルタがtrueと評価された場合、フレームが出力されるため、フレームのタイムスタンプt
を秒単位の特定のタイムスタンプと比較するチェックが追加されます(例:1.5
)これらのタイムスタンプのすべてのフレームが表示されます。