ffmpeg を使用して低品質のアニメーション GIF をすばやく生成するにはどうすればよいですか?

ffmpeg を使用して低品質のアニメーション GIF をすばやく生成するにはどうすればよいですか?

私たちはサムネイル GIF を大量に生成していますが、その品質よりも、生成にかかる時間が重要です。ffmpeg で高品質の GIF を生成する方法は非常によく説明されていますが、低品質の GIF をできるだけ早く生成する方法を見つけるのに苦労しています。

パレット計算は、次のコマンドで実行時間の大部分を占めます (マルチチェーン フィルターグラフの回答から抜粋):ウェブから直接ビデオ部分からベストパレット GIF を効率的に作成する方法):

ffmpeg -y -threads 8 -r 24 -f image2 -start_number 1 -i "frames.%04d.jpg" -filter_complex "fps=24,scale=150:-1:flags=fast_bilinear,split=2 [a][b]; [a] palettegen [pal] fifo [b]; [b] [pal] paletteuse" output.gif

1000 フレームのこのコマンドの実行時間は約 72 秒です。そのうち約 67 秒はパレット パスで、その後、実際の G​​IF 生成は約 5 秒で完了します。全体の実行時間をできるだけ短縮し、速度のために画質を大幅に犠牲にするつもりです。

答え1

palettegen/フィルターを使用すると、paletteuseコマンドの実行速度が遅くなります。低品質の GIF を実現する簡単な方法は次のとおりです。

ffmpeg -f image2 -i "frames.%04d.jpg" output.gif

追加のスケーリング:

ffmpeg -f image2 -i "frames.%04d.jpg" -vf scale=150:-1 output.gif

出力 GIF でフレームをドロップすることもできます。つまり、フレームをサンプリングして、すべてのフレームが処理されないようにすることができます。たとえば、フィルターを使用して 1 FPS 出力のみにするには、次のようにしますfps

ffmpeg -i "frames.%04d.jpg" -vf "fps=fps=1,scale=150:-1" output.gif

答え2

私の課題は、150ピクセル幅で長さ30フレームにできるだけ近いアニメーションGIFを生成するのにかかる時間を短縮することでした。私たちが生成するシーケンスのほとんどは1000フレーム未満です。15,000フレームのシーケンスがあり、レンダリングノードは17分この約 30 フレームの GIF を生成するには、許容できないほど時間がかかります。

私たちは ffmpeg をデマルチプレクサとして使用し、imagemagick にパイプしていました。数時間の実験を経て、私は次の結論に達しました。

  • ffmpegに処理させる入力フレームの数ははるかに実行速度の点で最も影響の大きい入力。入力フレームをスキップするために連結デマルチプレクサを使用するオプションがある場合、これが最大のパフォーマンスの違いを生み出します。5フレームごとに取得することで、合計計算時間を短縮できました。1分45秒高品質の Lanczos 再スケーリングとフレームごとのパレット計算を備えています。30フレームのプレビューサムネイルの生成に1秒もかかりません

  • 再スケーリング アルゴリズムは、次にパフォーマンスに大きな影響を与えました (ただし、2 番目に大きく離れています)。lanczos の代わりに fast_bilinear を使用すると、15,000 フレーム全体で 150 秒の計算時間が節約されました。

  • 最も影響の少ない変数はパレット計算であり、これは再スケール アルゴリズムによって異なります。Lanczos を使用して 15,000 フレーム以上を処理したところ、パレット計算を省くと実行時間が約 17 秒短縮されました。fast_bilinear を使用すると、実行時間が約 75 秒短縮されました。

再スケーリング アルゴリズムとパレット計算は無視できるほど小さいため、最終的には最高品質を維持することにしました。ffmpeg に入力ファイルの読み取りをスキップするように指示することで、計算時間を 17 分から 1 秒未満に短縮できました。

重要なポイント: 入力フレームのスキップと出力フレームのスキップ

プロセスに時間がかかった理由は、image2 デマルチプレクサを使用する場合、フレーム ドロップが実行時間の短縮に役立たないからです。フラグ-rfpsフィルターをいじると、最終的な GIF に表示されるフレームの数に影響しますが、ffmpeg は 15,000 個の入力フレームすべてに対して何らかの処理を行っているようです。

ffmpeg で入力フレームをスキップする方法として私が見つけた唯一の方法は、concatデマルチプレクサを使用することです。

入力フレームをスキップして、開発マシンで 1 秒以内に高品質のアニメーション GIF サムネイルを生成する方法は次のとおりです。

# create text file which describes the ~30 input frames we want ffmpeg to process
seq -f "file 'left_frames.%04g.jpg'" 10000 500 25000 > tmp.txt

# generate the animated gif using ffmpeg only
ffmpeg -f concat -i tmp.txt -filter_complex "scale=150:-1:flags=lanczos,split=2 [a][b]; [a] palettegen [pal]; [b] fifo [b]; [b] [pal] paletteuse" output.gif

関連情報