RemotionでアニメーションGIFを書き出す完全ガイド
RemotionでアニメーションGIFを書き出す完全ガイド
アニメーションGIFは死なない。1987年に生まれた画像フォーマットでありながら、2026年現在もSlackのスタンプ、メール本文内のアニメーション、GitHubのREADME、Notionページ、ブログ記事の挿絵として日常的に使われている。GIFが生き残り続けているのには明確な理由がある。JavaScriptが不要で、電子メールクライアントでも自動再生され、静的なMarkdownページにそのまま埋め込める。「動画を見るために別ページに遷移する」というステップが一切ない。
Remotionはこのニーズに応えるべく、gifコーデックによるネイティブGIF出力をサポートしている。プラグインや外部ツールは不要だ。すでに慣れ親しんだnpx remotion renderコマンドに--codec gifフラグを付けるだけで、任意のRemotionコンポジションをアニメーションGIFとして書き出せる。
この記事では、GIF出力に必要なCLIオプションのすべて、ファイルサイズを現実的な範囲に収めるための戦略、GIFの色制限にどう向き合うか、そしてMP4・WebMとどう使い分けるべきかを体系的に解説する。
RemotionのコーデックシステムにおけるGIF
Remotionが動画を書き出すとき、内部では各フレームを順番にレンダリングし、それを指定されたコーデックでエンコードする。MP4(H.264)やWebM(VP8/VP9)は時間軸方向の差分圧縮を行うため、動きの少ないシーンでは非常に高い圧縮率を実現する。
GIFコーデックはまったく異なる仕組みで動く。各フレームをインデックスカラー画像として独立して保存し、それを連続再生する。差分圧縮がないため、フレーム数が増えるほどファイルサイズは線形に増大する。この特性を理解した上で、GIFの出力設定を組み立てることが重要だ。
基本的なGIF書き出しコマンド
npx remotion render MyComposition output.gif --codec gif
これだけでGIFが生成される。ただし、デフォルト設定では数秒のアニメーションでも数十MBになることがある。実用的なGIFを作るためには以下の追加オプションが不可欠だ。
フレームレートとファイルサイズの制御
--every-nth-frameでフレームを間引く
GIFを適切なファイルサイズに収める最も効果的な手段は、出力するフレームを間引くことだ。--every-nth-frame(Node.js APIではeveryNthFrame)がその役割を担う。
# 30fpsのコンポジションを15fps相当のGIFに
npx remotion render MyComposition output.gif --codec gif --every-nth-frame 2
# 30fpsのコンポジションを10fps相当のGIFに
npx remotion render MyComposition output.gif --codec gif --every-nth-frame 3
実用的な判断基準:
everyNthFrame | 元コンポジション | 実効フレームレート | 適用シーン |
|---|---|---|---|
| 2 | 30fps | 15fps | ロゴアニメーション、UIデモ |
| 2 | 24fps | 12fps | テキストアニメーション |
| 3 | 30fps | 10fps | ゆっくりした動き、スライドイン |
| 4 | 30fps | 7.5fps | 静的に近いアニメーション |
動きの速いアニメーション(高速回転、素早いトランジション)は最低でも15fps必要だ。それ以下になると、なめらかさよりもカクつきが目立つ。
ループ回数を制御する
# 3回再生後に止まる
npx remotion render MyComposition output.gif --codec gif --number-of-gif-loops 3
# 1回だけ再生
npx remotion render MyComposition output.gif --codec gif --number-of-gif-loops 1
# 無限ループ(デフォルト動作)
npx remotion render MyComposition output.gif --codec gif --number-of-gif-loops 0
Slackスタンプやリアクション用GIFは無限ループ(0)が正解だ。ドキュメントに埋め込むプロダクトデモGIFは、読者の集中を妨げないよう2〜3回の再生に抑えるのが良い。
解像度の指定
npx remotion render MyComposition output.gif --codec gif --width 480 --height 480
解像度を下げることは、フレームレートを下げることと同等かそれ以上にファイルサイズへの影響が大きい。1080×1080のGIFと480×480のGIFでは、同じフレーム数・同じパレットでも面積比(5倍)の差が出る。さらに小さいキャンバスでは256色制限の粗さが目立ちにくいという副次的メリットもある。
GIFの256色制限を理解する
GIFはインデックスカラーフォーマットだ。1フレームあたり最大256色しか使えない。この制限はGIF規格そのものに起因するもので、Remotionの設定では変更できない。
実際の影響
グラデーションは縞模様になる。 #1a1a2eから#16213eへの滑らかなグラデーションには数百の中間色が必要だが、GIFはそのうち256色しか保存できない。結果として目に見える色の帯が生じる。
写真はほぼ使い物にならない。 写真には数百万色が含まれる。それを256色に量子化すると、ディザリングだらけの粗い仕上がりになる。写真コンテンツにはMP4かWebMを使うべきだ。
フラットデザインは完璧に機能する。 ソリッドな塗り、くっきりしたアウトライン、シンプルな配色のアイコンアニメーション、タイポグラフィアニメーション、インフォグラフィクスは256色制限の影響をほとんど受けない。
半透明は扱いに注意が必要だ。 GIFはバイナリ透明(完全透明か完全不透明)しかサポートしない。ぼかしたシャドウや半透明レイヤーがある場合、白いフリンジとして現れる。GIF向けのデザインでは、透明要素は使わないか、ハードエッジのマスクで代替する。
GIF向けのRemotionコンポジション設計
GIF出力を前提にデザインする際のチェックリスト:
- 背景はソリッドカラーを使う。グラデーション背景は避ける。
- 全体の色数を50色以内に抑えるよう意識する。
box-shadowはblur-radius: 0のハードシャドウを使う。ソフトブラーは避ける。- 大きなエリアが同時に変化するアニメーションはパレットエントリを消費するため、変化するエリアを最小限にする。
- アンチエイリアスによる白フリンジが気になる場合は、テキスト要素に
style={{ WebkitFontSmoothing: 'none' }}を適用する。
GIF、MP4、WebMの使い分け
GIFを選ぶべきケース
電子メール本文内のアニメーション。 ほとんどのメールクライアントは<video>タグをブロックする。Gmail、Outlook、Apple MailでアニメーションをHTMLメール本文内に入れる唯一の方法がGIFだ。
GitHubのREADMEとIssue。 GitHubのMarkdownレンダラーはGIFをインラインで自動表示するが、動画は自動再生しない。OSSプロジェクトのデモにGIFが定番な理由はここにある。
Notionページとドキュメントツール。 Notionはダウンロード不要でGIFをインライン表示する。動画ファイルは別扱いになる。
Slackカスタムスタンプ。 チーム独自のリアクションスタンプはSlackユーザーが最も喜ぶカスタマイズのひとつだ。Remotionでアニメーションスタンプを量産できる。
静的ブログのインライン挿絵。 JavaScriptが使えない静的サイトジェネレーター(Hugo、Jekyllなど)でもGIFは動く。
MP4を選ぶべきケース
Webページ内の動画。 <video autoplay muted loop playsinline>を使ったMP4は、同じ内容のGIFと比べてファイルサイズが1/10以下になることが珍しくない。品質も格段に高い。
グラデーションや写真コンテンツ。 色の再現精度が要求される場合はMP4一択だ。
音声が必要な場合。 GIFに音声トラックは存在しない。
10秒を超えるアニメーション。 GIFのファイルサイズは秒数とともに急増する。
WebMを選ぶべきケース
アルファチャンネル(透明背景)が必要な場合。 Remotionは--codec vp8でWebMを書き出せる。WebMはアルファチャンネルをサポートしており、任意の背景の上に合成できる。GIFのバイナリ透明では代替できない用途がここにある。
Node.js APIでバッチGIF生成
Slackスタンプを50枚一括生成するような用途では、Node.js APIが適している。
import { bundle } from "@remotion/bundler";
import { renderMedia, selectComposition } from "@remotion/renderer";
const bundleLocation = await bundle({
entryPoint: "./src/index.ts",
});
const stampData = [
{ label: "LGTM", accentColor: "#00c896" },
{ label: "Ship it", accentColor: "#ff6b6b" },
{ label: "Nice", accentColor: "#ffd93d" },
{ label: "Thanks!", accentColor: "#a78bfa" },
];
for (const stamp of stampData) {
const composition = await selectComposition({
serveUrl: bundleLocation,
id: "SlackStamp",
inputProps: stamp,
});
await renderMedia({
composition,
serveUrl: bundleLocation,
codec: "gif",
outputLocation: `./out/${stamp.label.toLowerCase().replace(/\s+/g, "-")}.gif`,
everyNthFrame: 2,
numberOfGifLoops: 0,
});
console.log(`完了: ${stamp.label}`);
}
renderMedia()のeveryNthFrameとnumberOfGifLoopsはCLIフラグと完全に対応しており、バッチ処理でも同じ制御ができる。
GIFファイルサイズのさらなる最適化
Remotionで書き出した後、外部ツールで追加の最適化が可能だ。
Gifsicle(無損失最適化):
gifsicle --optimize=3 --colors 128 input.gif -o output.gif
--colors 128でパレットを256から128に削減できる。デザインの色数が128以下であれば、視覚的な劣化はほぼなく、ファイルサイズは20〜30%削減される。
損失圧縮(gifsicle-lossy):
gifsicle --lossy=60 input.gif -o output.gif
損失値40〜80が実用的な範囲だ。60前後であれば、480px以下のサイズなら圧縮アーティファクトはほぼ気にならない。
RenderCompテンプレートでGIFをすぐに始める
ゼロからGIF向けコンポジションを設計するのが大変だと感じるなら、RenderCompのテンプレートライブラリが役に立つ。RenderCompでは、Slackスタンプ、メールヘッダーアニメーション、ブログ挿絵など、GIF出力に最適化されたRemotionテンプレートを提供している。各テンプレートはフラットカラー設計で、推奨レンダー設定(everyNthFrameとnumberOfGifLoops)があらかじめ設定されている。
rendercomp.comでテンプレートを探して、数分でGIFを書き出してみよう。
よくある質問
Q: RemotionのGIF出力にプラグインや外部ツールは必要ですか?
A: 不要です。GIFレンダリングはRemotionに組み込まれており、--codec gifフラグだけで有効になります。外部エンコーダーのインストールは不要です。
Q: --every-nth-frameを使うとアニメーションの速度が変わりますか?
A: いいえ、速度は変わりません。フレームを間引いてもGIFの再生タイムラインは元のコンポジションと同じ総時間になるよう調整されます。見た目の滑らかさが変わるだけで、アニメーションの「速さ」は変わりません。
Q: GIFに音声を含めることはできますか? A: できません。GIF規格は音声トラックをサポートしていません。音声が含まれるコンポジションをGIF出力しても、音声は無視されます。
Q: GIFの最大ループ回数に制限はありますか?
A: GIF規格ではループ回数を符号なし16ビット整数(0〜65535)で指定できます。0は「無限ループ」の特別値です。実用的には0(無限)か1〜5程度の値を使います。
Q: Outlook 2019でGIFが動かないと言われました。対処法は? A: Outlook 2016〜2019(Windows版)はGIFアニメーションをサポートしておらず、最初のフレームのみ表示します。対策として、コンポジションの最初のフレームをスタンドアロンの静止画として完結するようにデザインしてください。アニメーションは「見えたらラッキー」な体験として設計するのがメール向けGIFの鉄則です。
Q: Slackにアップロードするスタンプのサイズ制限は? A: Slackのカスタム絵文字は最大128×128ピクセル、ファイルサイズは10MB以内という制限があります。実際には200KB以内を目標にすると、多数のスタンプを登録しているワークスペースでも読み込みが速くなります。
Q: GIFで半透明の背景は実現できますか? A: 厳密な意味では不可能です。GIFはバイナリ透明(完全透明か完全不透明)しかサポートしません。PNG-8の「インデックス透明」と同等の機能です。アルファブレンディングが必要な場合はWebM(VP8コーデック)を使用してください。