ドキュメントサイトのデモ GIF をまとめて圧縮したところ、結果が三者三様でした。4 分の 1 になったもの、まったく変わらなかったもの、そして元より少し大きくなったもの。
ツールも設定も同じです。違っていたのは素材のほうでした。3 パターンを用意して測り直したので、その記録を残します。
検証環境
- ブラウザ:Chrome(ヘッドレス)、Network パネル常時オープン
- ツール:ImgIng のアニメーション工房(imging.ai)
- 素材:再現性を確保するため、すべてスクリプトで生成
ツールを選んだ理由は実務的なもので、フレーム分解と再エンコードがブラウザ内で完結するためです。素材が社内コンソールの画面収録だったので、できればアップロードしたくありませんでした。3 ファイル・十数回のエクスポートを通して POST リクエストは 0 件でした。この確認は F12 を開けば誰でも再現できます。
前提:上限はインポートした時点で決まっている
GIF には 2 つの制約があります。
1 フレームあたり最大 256 色。 256 本の色鉛筆で写真を模写するようなものです。必要な色がいくつあっても、その中から選ぶしかありません。
フレーム間は差分で保持される。 こちらはパラパラ漫画に近い動きです。前のページと右下の一部しか違わないなら、その一部だけ描けばよい。エンコーダも同じことをしていて、前フレームと同一のピクセルは保存し直しません。
つまり削減余地を決めるのは「どれだけ静止しているか」であり、これは品質スライダーの管轄外です。
実測 1:画面収録タイプ
720×405、36 フレーム、2.88 秒。コンソール風 UI で、6 行のリストは終始静止し、動くのは進捗バーとカーソルのみ。
- 79.8 KB → 21.3 KB(−73%)
- 自動判定:GIF 維持・64 色
静止領域が支配的なため差分が効き、フラットな配色なので 64 色でも見た目に差が出ません。
実測 2:全面ノイズタイプ
480×320、24 フレーム。毎フレーム乱数で再生成しており、時間方向にほぼ一致するピクセルがありません。
- 2.62 MB → 2.63 MB(横ばい)
- 自動判定:GIF 維持・256 色
- UI 側の表示:「小さくなりませんでした — この映像は GIF に向きません。WEBP のほうが小さく鮮明になります」
静止ピクセルがほぼゼロなので差分は無効、色数も上限に張り付いており減色はディザリングのコストだけが残ります。両方の手段が塞がれた状態です。
なお挙動として、小さくできない場合は元ファイルをそのまま保持し、その旨を通知する設計になっていました。より大きな成果物を黙って返す実装も現実に存在するため、この点は明記しておきます。
実測 3:すでに最適化済みの小さな GIF
120×120、8 フレーム、3 色のローディングアニメーション。
- 2.0 KB → 1.5 KB(−25%)
- 自動判定:GIF 維持・16 色
すでに小さいにもかかわらず 4 分の 1 削れたのは、256 項確保されていたパレットを実使用の 16 色まで縮めたためです。ただしここが終点で、これ以上はサイズ縮小・フレーム削減・画質低下のいずれかになります。それは圧縮ではなく編集です。
まとめ:3 つの落とし穴
1. 動画的な映像を GIF で処理しようとする。 動画書き出し、実写、グラデーション、ノイズ。これらは圧縮が難しいのではなくコンテナの選択が誤っているだけです。
2. 最適化済みの GIF を再圧縮する。 配布されているスピナーや素材はたいてい減色と差分が済んでいます。目安として ファイルサイズ ÷(幅 × 高さ × フレーム数) が 1 バイト/ピクセルを大きく下回っていれば、ほぼ限界です。
3. コンテナを替えれば小さくなると考える。 アニメーション WebP が GIF より小さいのは 256 色制限がなく非可逆エンコードが使えるからで、再エンコードによる効果であって再梱包による効果ではありません。
適用範囲について
上記 3 組の数値は、性質を意図的に振り切った自作素材によるものです。「あなたの GIF が何 % 減るか」の推定には使えません — 圧縮結果は元素材に完全に依存し、同じ映像でもサイズが変われば結果も変わります。読み取れるのは仕組みのほうです。静止ピクセル比率とパレットサイズが上限を決め、パラメータはその内側でしか働きません。
もう一点付け加えると、「小さくならない」が正しい答えであることもあります。すでに最適化済みの素材に対して、変化なしと伝えて元ファイルを残す挙動は、より大きなファイルを返すより誠実だと考えています。