私はffmpegを使用して、このコマンドを使用して1秒あたり3フレームを抽出しています
ffmpeg -i input.flv -f image2 -vf fps=fps=3 out%d.png
Fps値を設定した場合、ffmpegは1秒間に3フレームをどのように選択するのでしょうか。それはランダムですか、それともその秒の最初の3フレームかかりますか?何か助けはありますか?
これは、タイムスタンプ値を入力タイムベース(つまり、FPSを小数として、たとえば24fpsが1/24になる)から出力タイムベースに再スケーリングすることによって行われます。
まず、要求されたFPSに基づいて タイムベースが設定されます :
link->time_base = av_inv_q(s->framerate);
フィルタリングの場合、出力フレームの数は、バッファ内の入力フレームの数に基づいて計算され、2つのタイムベース間でその数がスケーリングされるため、基本的にフレーム×入力/出力。ご了承ください buf->pts - s->first_pts
は明らかにフレーム数であり、PTS時間の実際の違いではありません。
/* number of output frames */
delta = av_rescale_q_rnd(buf->pts - s->first_pts, inlink->time_base,
outlink->time_base, s->rounding) - s->frames_out ;
したがって、たとえば、入力タイムベースが0.042(24 fps)、出力が0.33(3 fps)で、バッファに12フレームの入力がある場合、12×0.042 /0.33が得られます。 フレーム。次に近い整数2に丸められます。したがって、2つのフレームが生成されます。 24フレームの場合、もちろん3フレームになります。入力バッファの35フレームの場合、4つの出力フレームを取得します。
そのデルタが1より小さい場合、この時間範囲ではフレームが必要ないため、バッファ内のフレームをドロップできます。一方、デルタが1より大きい場合は、入力バッファーに出力する必要のあるフレーム数です。
新しいフレームの場合、PTS値は入力および出力のタイムベースに基づいてスケーリングされます。
buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
outlink->time_base) + s->frames_out;
実際には、これは、入力ビデオのPTSを確認し、出力が持つことができる1秒あたりのフレーム数を計算してから、必要に応じてフレームをドロップすることによってそれらを均等に分散する必要があることを意味します。非常に正確にしたい場合は、いくつかのテストビデオを使用してソースコードをデバッグすることをお勧めします。
フレームレートが変更されたビデオで各フレームのPTSを表示する方法を説明する答えI 最近ここに投稿 よりも実用的な解決策を思い付くことができないのではないかと思います。
ffmpeg -i input.mp4 -t 10 -filter:v "fps=fps=25, showinfo" -f null - 2>&1 grep pts_time | awk '{print $6}' | cut -d: -f2
これらのタイムスタンプは、すべての出力フレームとそれに対応する入力PTS時間に属します。