動画 → スクロール駆動型ランディングページ
Apple製品ページやGitHub Copilotのランディングのように、スクロールに応じて動画が再生されるシネマティックなランディングページを構築します。ソース動画からフレームを抽出し、ユーザーのスクロールに合わせてフレームを切り替えます。スティッキーなヒーローの下には、通常のスクロールでコピーとCTAが続きます。
呼び出すタイミング
- ユーザーが動画をドロップし、「ランディングページ」「スクロールサイト」「スクロールフレームヒーロー」「動画からウェブサイト」などを依頼した場合
- 「Apple風スクロール」「GitHub Copilotランディング」「スクロールに連動」「スクロールでフレーム切り替え」などの言及があった場合
- 日本語での同様の依頼:
- 「動画からランディングページを作って」
- 「スクロールで動画が再生されるサイト」
- 「Apple製品のページみたいなスクロールサイト」
保存場所
デフォルト: ~/Documents/yuv-projects/landings/<slug>/ — 後で見つけられるように、ランディングページは常にここに保存します。親ディレクトリが存在しない場合は作成します。
mkdir -p ~/Documents/yuv-projects/landings
cd ~/Documents/yuv-projects/landings
# ここに <slug>/ を構築します。
最終パス: ~/Documents/yuv-projects/landings/<slug>/。ビルドの最後にユーザーにランディングページの場所を伝えてください。
ワークフロー(8ステップ)
- ソースのプローブ —
ffprobeで長さ、fps、寸法、オーディオを取得。 - フレーム数を決定 — デフォルト
80。下限40(これより低いとカクつく)、上限160(ページが重くなる)。動画の長さで選択:≤10秒→50、10〜30秒→80、30〜60秒→120、>60秒→160。 - 出力ディレクトリを決定 — デフォルト
~/Documents/yuv-projects/landings/<slug>/。<slug>は短く、動画ファイル名またはトピックから派生させます。明示的なリクエストがある場合のみ上書き。 - フレームを抽出 —
references/extract-frames.py <source-video> <output-dir> [count]を実行。出力はoutput-dir/frames/f_0001.jpg… 一貫したJPG品質82、最大幅1920(ソースがより大きい場合は縮小)。 - テンプレートをコピーしてカスタマイズ —
references/landing-template.htmlをoutput-dir/index.htmlにコピー:__FRAMES__プレースホルダーを各フレームの<img>タグに置き換え(ビルドスクリプトが--build-htmlを渡すと自動で行います)。__HEADLINE__、__TAGLINE__、__CTA_TEXT__、__CTA_HREF__、セクションを埋める。- コンテンツが日本語の場合:
<html lang="ja" dir="ltr">を設定。フォントは Noto Sans JP / Noto Serif JP などを使用(references/design-notes.mdを参照)。
- フレームを最適化 — ビルドスクリプトはすでに最大幅1920pxにスケーリングします。ページの総容量が12MBを超える場合は、品質を75に下げるか、フレーム数を減らします。
- プレビュー — 出力ディレクトリ内で
python -m http.serverを実行し、http://localhost:8000を開きます。普通のマシンでもスムーズにスクロールできます。 - デプロイ — フォルダを Vercel/Netlify/Cloudflare Pages にドロップします。ビルドステップは不要です。
スクロールの仕組み
- 外側のスクローラー
.scroll-stageの高さはビューポート単位で設定(デフォルト600vh= 全フレームを通過するのに5画面スクロール)。 - スティッキーヒーロー
position: sticky; top: 0; height: 100vhには、すべてのフレームが絶対配置され、アクティブなもの以外は非表示。 - スクロールリスナーは
progress = scrolledIntoStage / scrollableHeightを計算し、0〜1にクランプ。 idx = floor(progress * (N - 1))—.activeクラスをそのフレームに切り替え。- リスナーを
requestAnimationFrameでラップして60fpsを維持。
デザインルール
- プロジェクトが YUV.AIブランド(Yuval個人、彼のポートフォリオ、彼のブランド)の場合:
yuv-design-systemを呼び出し、メディアに応じてモードを固定します —- Neonモード(YUV.AIウェブのデフォルト):ホットピンク(
#FF1464)+ ネオンシアン(#00E5FF)+ ホワイトまたはリッチブラックのキャンバス。Anton + Inter(英語)/ 日本語の場合は適切なフォント。0pxまたは999pxの角丸。 - Warm Editorialモード: Hope、Marcus、bigcats.ai、practical.yuv.ai のみ — ピンク + イエロー + ボーン、オフホワイト(純粋な
#fffは使用しない)。 - ランディングページでは Decksモード(Fly High パープル/イエロー)は使用しない — このパレットはスライドデッキ専用です。
- Neonモード(YUV.AIウェブのデフォルト):ホットピンク(
- プロジェクトが YUV.AIブランドでない 場合:yuv-design-system は適用しません。ソース動画の雰囲気に合ったパレットを選びます。Anton + Inter は適切なデフォルトとして残りますが、必須ではありません。
- ヒーローのオーバーレイは控えめに — ビネットと1つの大きな見出しのみ。フレームを覆いすぎないように。
- ヒーロー下のセクション:明るいキャンバス(Neonモードでは白、Warm Editorialではオフホワイト、汎用ウォームではボーン)、大きなAnton見出し、本文はInter 18〜22px、CTAはシャープなピル型(
border-radius: 999px)— Neonモードではピンク塗り、それ以外ではブランドに適した色。 - 日本語の場合:適切なLTRレイアウト、見出しに適切なウェイト(例:Noto Sans JP Bold)、本文に標準的なウェイト(例:Noto Sans JP Regular/Medium)を使用。
ファイル参照
| ファイル | 目的 |
|---|---|
references/extract-frames.py | ffmpegベースのフレーム抽出器。オプションでHTMLも一度にビルド |
references/landing-template.html | スクロール機構を備えた自己完結型ランディングページのスケルトン |
references/design-notes.md | タイポグラフィ、パレット、モーションのデフォルト設定 |