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

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

主な特徴

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

公式ドキュメント

フィルタの解説記事

関連記事

High quality GIF with FFmpeg

palettegenのオプション

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

  • max_colors[int]
    パレットで使う色の最大値を指定する
    既定値:256
    範囲:4 から 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

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:既定値
  • 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まで

コマンドサンプル

基本コマンド

静止画像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

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

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

コメントを残す

メールアドレスが公開されることはありません。

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