16×16(つまり256パターン)の色をパレットに一時出力し、それを使って色を最適化したファイルが出力する。これにより最適化されたアニメ-ションGIF(アニメGIF、AGIF)や、色の少ないPNG圧縮で効果が期待できる。

16×16 のパレットを作るpalettegenフィルタと、パレットを元に出力するpaletteuseフィルタに分けられる。

2023年1月4日のコミットでアルゴリズム周りで大きく改修された。

主な特徴

  • 最大256色まで、透過出力はできない
  • 透過部分のグラデーションはできない。透過するかしないだけになる
  • 色の少ない PNG の色を最適化して圧縮したりアニメGIF向き
  • PC画面のスクリーンショットの画像を圧縮するのに重宝できそう
  • フルカラーの JPG は意味がない
  • 同様に動画にも不向き、グレインが大量に付いて容量が増える
  • フルカラーなどの素材にmax_colorsでパレットの色を制限するのは容量の面で効率が良くない(と思う)。この場合にはpixeliz0rフィルタを使って細かいモザイクに加工することでドット絵風にすることができる
  • 基本的にはデフォルトの設定で良い

公式ドキュメント

フィルタの解説記事

関連記事

High quality GIF with FFmpeg
How do I convert a video to GIF using ffmpeg, with reasonable quality? – Super User

palettegenのオプション

16×16ピクセルのパレットを作る
ffmpeg -i input -vf palettegen=max_colors=256:reserve_transparent=1:transparency_color=lime:stats_mode=full -update 1 -frames:v 1 palette.png

  • max_colors[int]
    パレットで使う色の最大値を指定する
    既定値:256
    範囲:2 から 256 まで
  • reserve_transparent[boolean]
    パレットに透過色を使う。アニメGIFの時に有効化するとうまく最適化される。1枚画像の時には無効にした方がよい
    既定値:1(有効)
  • transparency_color[color]
    透過の背景色の指定
    既定値:lime
  • stats_mode[int] 統計モード
    • 0, full
      全フレームのヒストグラムから計算する。既定値
    • 1, diff
      前フレームの動いている部分のヒストグラムから計算する
    • 2, single
      毎フレームパレットを作る

metadataを使って元のフレームに何色使われていて、それがどれくらい減色されたのかを調べることができる。
ffmpeg -i img -vf palettegen,metadata=print:key=lavfi.color_quant_ratio -f null -

singleモードで毎フレームパレットを作る例。
ffmpeg -i input -vf palettegen=stats_mode=single -an -c:v ffv1 palette.mkv

メタデータ出力内容。

lavfi.color_quant_ratio

paletteuseのオプション

パレットを使って減色処理を行う。
ffmpeg -i input -i palette.png -filter_complex paletteuse=dither=bayer:bayer_scale=2 output.gif

複数フレームのパレットを読み込む例。
ffmpeg -i input -i palette.mkv -filter_complex paletteuse=new=1 output.gif

  • dither[int] 設定できるディザーのアルゴリズムは以下
    • 0, none:容量は一番小さくなるがバンディングが目立つ。つまりグラデーションがきれいにならない
    • 1, bayer
    • 2, heckbert
    • 3, floyd_steinberg
    • 4, sierra2
    • 5, sierra2_4a:既定値
    • 6, sierra3
    • 7, burkes
    • 8, atkinson
  • bayer_scale[int]
    ディザーにbayerを使ったときに0から5までの整数が指定できる
    0に近いほどグレインは目立つがバンディングは目立たない
    5に近いほどグレインは目立たないがバンディングは目立つ
    既定値:2
    範囲:0 から 5 まで
  • diff_mode[int]
    • 0, none:既定値
    • 1, rectangle:映像の一部だけ動いてる場合により最適化される。そうでない場合使わない方が良い
  • new[boolean]
    複数フレームのパレット入力に対応する。フレーム毎に色が異なるのでその分だけ高画質になるが容量は増える
    既定値:0(対応しない)
  • alpha_threshold[flags]
    透過部分の閾値の指定。指定値を超えると不透過になり、下回ると完全な透過になる
    既定値:128
    範囲:0から255まで
  • debug_kdtree[string]
    Graphvizグラフのkdtreeを指定した場所とファイル名で保存する
    既定値:無指定

コマンドサンプル

基本コマンド

静止画像GIF、PNGの場合。PNG出力なら色の少ない画像だとこれも容量削減になる。
ffmpeg -i input -filter_complex palettegen=reserve_transparent=0 tmp.png
ffmpeg -i input -i tmp.png -filter_complex paletteuse output.gif
ffmpeg -i input -i tmp.png -filter_complex paletteuse output.png

実際に使う場合には1行コマンドで実行する方が手軽。
ffmpeg -i input -filter_complex "split[a][b];[a]palettegen[pal];[b][pal]paletteuse" output.png

VLC画面の圧縮比較

オリジナル画像(PNG):27.9 KB

この方法で圧縮した画像(PNG):17.7 KB(約37%減)

動画からアニメGIFを作る

動画からパレットを使ってアニメーションGIFを出力する例。ポイントは-ss、-tを入力オプションで使うところ。適宜フレームレートfpsやリサイズscaleする。以下の例は開始10秒から4秒間で10fpsの横幅320ピクセルでアスペクト比を保持してリサイズしたGIFを出力。
ffmpeg -ss 10 -t 4 -i input -filter_complex "fps=10,scale=320:-2,split[a][b];[a]palettegen[pal];[b][pal]paletteuse" output.gif

容量は大きくなるが、フレーム毎にパレットを使って減色するならpalettegen=stats_mode=2paletteuse=new=1をつける。
ffmpeg-i input -filter_complex "split[a][b];[a]palettegen=stats_mode=2[pal];[b][pal]paletteuse=new=1" output.gif

動画ファイルを読み込むときに時間が長いほど全てのフレームを調べるのに時間が掛かるので、動画ファイルからパレットを作るときは前もって時間指定してカットしておくか、trimフィルタを使ってカットする。
ffmpeg -i input -filter_complex trim=start_frame=1536:end_frame=1667,scale=320:-2,palettegen tmp.png
ffmpeg -i input -i tmp.png -filter_complex trim=start_frame=1536:end_frame=1667,scale=320:-2,paletteuse output.gif

1行コマンドなら以下のようになる。
ffmpeg -i input -filter_complex "trim=start_frame=1536:end_frame=1667,scale=320:-2,split[a][b];[a]palettegen[pal];[b][pal]paletteuse" output.gif

ループ回数は-loopを指定する。-1がループしない1回再生。0が無限ループ。1が1度だけループして2回再生。2が2度だけループして3回再生。以下同様。

ffmpeg -ss 10 -t 4 -i input -filter_complex "fps=10,scale=320:-2,split[a][b];[a]palettegen[pal];[b][pal]paletteuse" -loop 0 output.gif

ヘルプコマンド:ffmpeg -h muxer=gif

Gifsicleを使ってさらにGIFを最適化できる。

2色だけ、3色だけに減色する映像効果
輝度の段差を減らして容量を減らす試み

One thought on “ffmpeg で 256色を最適化する palettegen, paletteuse”

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)