Picovert

GIFをMP4に変えてLighthouseスコアを64から92に上げた記録

Picovert チーム著2026-04-258分で読了

ファーストビューにアニメーションGIFが3つ並ぶマーケティングランディングページがありました — 製品の動きを見せるヒーローループに、機能アニメ2本。合計11MB。Lighthouseはモバイルで ページを64と評価し、LCPは4.2秒、Total Blocking Timeは380ms。3本のGIFを MP4に置き換えただけで — 同じビジュアル、同じループ挙動 — その日の午後のうちに92に乗りました。本記事は実況中継です。

出発点

ページは標準的なNext.jsマーケサイト。Tailwind、静的生成、Vercelデプロイ。3本のGIFはAfter Effectsから720p、30fps、適度な最適化で書き出したもの。サイズ:

  • ヒーローアニメ (5秒、720p): 5.8 MB
  • 機能1 (3秒、600p): 2.9 MB
  • 機能2 (4秒、600p): 2.4 MB

アニメのペイロード合計: 11.1MB。Slow 4G (Lighthouseモバイルプロファイル) では完全ロードまで およそ27秒。テキストは早く描画されたものの、ヒーローはずっと「読み込み中」のプレースホルダ のままで、これがまさにLCPが罰する状態です。

出発時点のLighthouseレポート

指標スコア
Performance64
Largest Contentful Paint4.2秒
Total Blocking Time380ms
Speed Index5.8秒
Cumulative Layout Shift0.04

変換

各GIFを2設定でffmpegに通しました: 広く使えるフォールバック向けにH.264 MP4、対応ブラウザで さらに小さくなるVP9 WebM。コマンド:

ffmpeg -i hero.gif -movflags faststart -pix_fmt yuv420p -crf 22 -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2:flags=lanczos" -an hero.mp4

ffmpeg -i hero.gif -c:v libvpx-vp9 -crf 30 -b:v 0 -deadline good -cpu-used 2 -row-mt 1 -pix_fmt yuv420p -an hero.webm

変換後のサイズは衝撃的でした:

素材GIFMP4 (H.264)WebM (VP9)
ヒーロー5.8 MB320 KB (-94%)240 KB (-96%)
機能12.9 MB180 KB (-94%)140 KB (-95%)
機能22.4 MB150 KB (-94%)110 KB (-95%)

合計ペイロードはH.264で11.1MB → 650KB、VP9で490KB。17〜22倍の削減です。

マークアップの変更

元のマークアップは <img src="hero.gif" alt="...">。差し替え:

<video autoplay loop muted playsinline poster="hero-poster.jpg">
<source src="hero.webm" type="video/webm">
<source src="hero.mp4" type="video/mp4">
</video>

posterは動画がデコードを始める前に表示される静止フレーム(JPEG、約30KB)。 これがLCPの解錠ポイントでした — ブラウザがposterをcontentful paintとして認識し、1秒以内 に到達しました。

変換後のLighthouseレポート

指標
Performance6492
LCP4.2秒1.4秒
TBT380ms110ms
Speed Index5.8秒1.9秒
CLS0.040.02

LCPは67%減、TBTは71%減。TBTが改善した理由: ソフトウェアGIFデコードがフレームごとに メインスレッドをブロックしていたから。ハードウェアMP4デコードは別プロセスへオフロードされます。

注意点と落とし穴

  • autoplayにはmuted必須。iOSと2018年以降の大半のブラウザは音声付き動画の 自動再生をブロックします。autoplayループには常にmutedを。
  • iOSにはplaysinline必須。無いとiOSがタップ時に全画面プレイヤーで開きます。
  • H.264は偶数寸法。コーデックは幅も高さも2の倍数を要求します。scale=trunc(iw/2)*2:trunc(ih/2)*2フィルタを。
  • Safariにはyuv420p必須。他のピクセルフォーマットはChromeでは通っても Safariで静かに失敗します。
  • 静的な装飾に動画を使わない。「アニメ」がほぼ動かない(緩いズームや繊細な パン)なら、静止画やCSSアニメの方が安価です。

Lighthouseの先: 実ユーザーへの影響

Lighthouseの数値は合成スコア。本当に見るべきはフィールドデータ — 実際のネット越しの実際の 訪問者です。変更後2週間で見えたもの:

  • 本番のp75 LCP: 3.8秒 → 1.6秒 (Chrome User Experience Report)
  • 直帰率: モバイルで -8% (GA計測)
  • CDN帯域請求: マーケサイト単体で -$340/月

帯域節約より、それまでパレット技や誤差拡散でGIFをさらに絞ろうと費やしたエンジニアリング 時間の方がはるかに高くついていました。フォーマットの境界を越えた瞬間、その努力はすべて 無関係になりました。

自分のサイトでやる方法

64から92へ連れて行った5ステップ:

  1. DevToolsのNetworkタブでページ上の.gifをすべて見つける。
  2. それぞれをMP4 (H.264)とWebM (VP9)に変換。単発なら私たちのGIF → MP4 変換ツールが両フォーマットに対応し、 ブラウザ内で動きます。パイプラインなら上のffmpegコマンドを。
  3. 各動画に静止フレームのposter JPEGを生成。ffmpeg -i input.gif -vf "select=eq(n\\,0)" -vframes 1 poster.jpg
  4. <img>を上記の<video>に置き換える。
  5. Lighthouseを再実行。スコアが跳ねたか、LCPが下がったかを確認。

所要時間: 私たちが管理するサイトで1ページあたり約20分。何千ものユーザーの全ページビューに 効いてくる複利効果のおかげで、今年やった性能修正の中でも単発で最もテコ入れの大きい仕事に なりました。