Base64 を GIF に変換する方法
- 入力欄に Base64 か
data:image/gif;base64,...形式の URI を貼り付けるか、それを含む.txtファイルを開きます。 - ステータス行の 検出 に GIF と表示されていることを確認します。プレビューでアニメーションの再生が始まり、その上にピクセルサイズが表示されます。
- ファイルをダウンロード を押して
.gifとして保存します。
描き直しや再圧縮は一切しません。保存したファイルは、エンコードされた GIF と同じフレーム、遅延時間、パレット、透過を持ちます。
本当に GIF か、アニメーションか
GIF は GIF89a か GIF87a で始まり、Base64 では R0lGODlh か R0lGODdh になります。アニメーション、透過、ループの制御にはどれも新しい 89a 版が必要なので、R0lGODdh で始まる文字列は事実上静止画です。
89a のファイルが動くかどうかは、中身の画像ブロックが 1 つか複数かで決まります。プレビューを見ればひと目で分かります。さらに詳しく見るには、16進ダンプを表示 を開いてください。アニメーション GIF には、たいてい ASCII の列に NETSCAPE2.0 というテキストがあります。これがループ回数を持つブロックです。カラーテーブルが小さければ最初の数行に現れます。256 色のカラーテーブルを持つ GIF では先に 768 バイトのパレットが来るので、このブロックはダンプに表示される 512 バイトより後ろにずれます。
ページが「これは GIF ではなく WebP のようです。」と表示したり MP4 と判定したりした場合、その「GIF」は途中で変換されています。メッセージアプリや GIF 検索サービスは、ずっと小さくなる WebP や MP4 動画でアニメーションを配信することがよくあります。.webp としてダウンロード のようなボタンで本来の拡張子で保存するか、MP4 なら Base64 を動画に変換 で開いてください。
コードでフレーム、タイミング、ループを調べる
エディターを開かずに GIF を調べるなら、Pillow で必要な情報をすべて読めます。
import base64, io
from PIL import Image
def gif_info(b64: str) -> dict:
data = base64.b64decode(b64.split(",", 1)[-1])
with Image.open(io.BytesIO(data)) as im:
durations = []
for i in range(getattr(im, "n_frames", 1)):
im.seek(i)
durations.append(im.info.get("duration", 0))
return {
"size": im.size,
"frames": len(durations),
"total_ms": sum(durations),
"loop": im.info.get("loop"),
}
1 フレーム 100 ms で 3 フレームのテスト用アニメーションなら、{'size': (20, 20), 'frames': 3, 'total_ms': 300, 'loop': 0} が返ります。loop が 0 なら「無限に繰り返す」、None ならファイルにループブロックがなく 1 回だけ再生されるという意味です。ファイルの扱いについては Python での Base64 で詳しく解説しています。
Base64 の GIF はどこから来るのか
data:image/gif;base64,...としてインライン化された CSS や HTML の読み込みスピナー。CSS アニメーションや SVG が普及する前からの習慣です。- 小さなアニメーションロゴを埋め込んだ、古い HTML メールのテンプレートや署名。
- スタンプやリアクションを Base64 のフィールドとして含む API レスポンスやチャットのエクスポート。
- プレースホルダーのピクセル:空の
srcとして使われる 1×1 の GIF です。プレビューは空白に見えるので、デコードに失敗したと考える前に寸法を確認してください。
デコード後の GIF のサイズ
GIF はすべてのフレームを古い圧縮方式で保存するので、短いアニメーションでもすぐに数 MB に達し、Base64 にするとさらに 3 分の 1 増えます。サイズ の行にはデコード後のサイズが表示されます。「小さな」GIF の文字列が 5 MB なら、GIF 自体は約 3.75 MB です。ここでデコードするのは問題ありませんが、ページにインライン化し直すには向きません。作り直すなら、短い MP4 や WebM のループのほうがたいてい何分の 1 かのサイズで済みます。GIF をエンコードするには、GIF を Base64 に変換 を使ってください。
よくある質問
デコードした GIF が 1 回しか再生されないのはなぜですか?
ループの設定はファイルの一部だからです。NETSCAPE2.0 ブロックがないか、ループ回数が 1 の場合、ブラウザはアニメーションを 1 回再生して最後のフレームで止まります。デコードではファイルの設定をそのまま保つので、変更するには GIF エディターを使ってください。
Base64 の GIF のフレーム数を数えるには?
プレビューは GIF を再生しますが、フレーム数は数えません。Python なら Pillow の n_frames でフレーム数が分かり、フレームごとの duration を合計すると全体の長さになります。このページのスニペットで両方を求められます。
GIF が途中で止まる、または最後のフレームが崩れるのはなぜですか?
Base64 が途中で切れています。ブラウザは届いたフレームを再生し、データが終わったところで止まります。完全な GIF はトレーラーバイト 3B で終わるので、その Base64 はたいてい ADs=、Ow==、A7 のいずれかで終わります。