scroll-video-website について
動画に連動するスクロールサイトを構築・最適化するスキルです。コーディングエージェント向けに、フレーム抽出、Canvas描画、レスポンシブ対応、アクセシビリティ、検証を案内します。
主な機能
- 01スクロール連動動画体験の構築
- 02番号付きWebPフレームの抽出
- 03Canvasでの描画とクロスフェード
- 04フレームの段階的な読み込み
- 05視差効果を減らす設定への対応
活用シーン
- 01製品動画をスクロール演出に変換
- 02動画主体のスクロールストーリーテリング
- 03既存のアニメーション用フレーム列の最適化
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ musoyangrigor/ scroll-video-website-skill --skill scroll-video-websiteインストール後、Claude Code で/scroll-video-websiteを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlreferences/optimize.md
詳細
スクロール動画ウェブサイト
使用する場面
次のような要望がある場合に、このスキルを使用します。
- 動画から Apple スタイルのスクロールアニメーションを作成する
- スクロール操作に連動する動画ウェブサイトを作成する
- 製品動画を、映画のようなランディングページにする
- 動画を使ったスクロールテリング体験を構築する
- 動画を、スクロールアニメーション用に最適化された画像シーケンスに変換する
- スクロール操作で制御する、Canvas ベースの製品紹介を作成する
- 既存の生成済みスクロール動画フレームシーケンスを最適化する
通常の自動再生動画背景や、無関係なスクロールエフェクトには使用しないでください。
製品アニメーションビューアーのような、シンプルなフルページ体験を作成します。ページ自体がスクロール距離を確保し、固定された Canvas がビューポート全体を占め、ユーザーの動画から生成したフレームシーケンスをスクラブ再生します。アニメーションがインターフェースそのものであり、従来のランディングページの背景ではありません。
呼び出し方法
このスキルには、動画からスクロール動画ウェブサイトを構築するモードと、既存のフレームシーケンスを最適化するモードがあります。最初の引数が optimize の場合は、references/optimize.md に従い、以下のビルドワークフローは実行しないでください。
次の簡潔な形式を、ビルド依頼全体として扱います。
$scroll-video-website <path/to/video.mp4>
動画のパスは、スキル名の後の最初の引数である必要があります。パス以降の内容はすべて、スタイル、レイアウト、コピー、動作に関するユーザーの任意の指示です。
$scroll-video-website ./media/product-reveal.mp4
$scroll-video-website ./media/product-reveal.mp4 use a black background and condensed typography
1つ目の例は、フレームシーケンスを生成し、以下で説明する既定のスクロールアニメーションウェブサイト全体を構築することを意味します。2つ目の例では、動画を使った同じアニメーション構成を維持しながら、追加されたビジュアル指示に従います。このスキルはスタイルオプション用の別個のコマンド文法を定義していません。残りのプロンプトの解釈と実装は、このスキルを使用するエージェントに任せてください。
動画のパスは、絶対パスでない限り、現在の作業ディレクトリからの相対パスとして解釈します。パスにスペースが含まれる場合、ユーザーはパスを引用符で囲む必要があります。まず指定されたパスをそのまま確認してください。ファイル名だけが指定され、その場所にファイルがない場合は、依存関係、ビルド、キャッシュ、VCS のディレクトリを除外して、現在のプロジェクト内から完全一致するファイル名を検索します。一致するものが1つだけ見つかった場合は、そのまま続行します。一致するものがない場合、または複数ある場合は、正確なパスをユーザーに尋ねてください。<path/to/video.mp4> や {video_path} の波括弧はプレースホルダーを示すもので、実際のパスには含まれません。use キーワードを必須としたり、その意味を解釈したりしないでください。
既存のシーケンスを最適化する場合は、次のコマンドをそのまま使用します。
$scroll-video-website optimize
最適化コマンドには、パスやその他の引数を指定しません。生成済みのフレームシーケンスがないか、現在のプロジェクトを調べます。シーケンスを1つだけ特定できた場合は、そのまま続行します。複数のシーケンスを特定できた場合は、それらを提示し、どれを最適化するかユーザーに尋ねます。シーケンスが見つからない場合、または確実に特定できない場合は、frames フォルダーが見つからなかったことをユーザーに伝え、停止します。
プロジェクトとソース動画の確認
編集を始める前に、次の手順を行います。
- プロジェクトの構成、スクリプト、フレームワーク、スタイリング、ルーティング、アセットの規約、ローカルの指示を確認します。
- 上記の呼び出しルールに従って、ユーザーが指定した動画を探します。動画もパスも指定されておらず、確実に特定できる動画もない場合は、実装を始める前にユーザーに確認します。
- 既存の動作する技術スタックを再利用します。すでに動作するプロジェクトがある場合は、代替プロジェクトを新たにスキャフォールドしないでください。
ffprobeが利用できる場合は、動画の寸法、再生時間、フレームレート、フレーム数、ファイルサイズを確認します。- 無関係な動作を維持し、整合性のある最小限の変更だけを加えます。
代替アートを作成したり、指定された映像を置き換えたりしないでください。ビルドで必要な場合を除き、ソース動画を重複して保存しないでください。
動画をフレームシーケンスに変換する
デフォルトの描画方法は、video.currentTime ではなく、番号付きの WebP フレームシーケンスです。プロジェクトの公開/静的アセット領域に、frames/frame_0001.webp のようなゼロ埋めした名前でフレームを抽出します。
- 元動画のフレームレートは最大 30 fps まで維持します。長いクリップでは、ペイロードを実用的なサイズに保つため、全体を約 240~300 フレームにサンプリングします。
- 元動画のアスペクト比を維持します。WebP の品質は 78~82 程度を目安にし、設定で十分だと決めつけず、出力を確認します。
- 実際に抽出したフレーム数を実装に記録します。推測した定数を残さないでください。
- 抽出には
ffmpegを優先します。代表的なコマンドはffmpeg -i input.mp4 -vf fps=30 -c:v libwebp -quality 80 frames/frame_%04d.webpです。入力、fps、出力先、既存のプロジェクトツールに合わせて調整してください。 - 関係のないアセットを削除したり上書きしたりしないでください。出力先にすでにシーケンスがある場合は、置き換える前にそのアニメーションのものか確認してください。
フレーム抽出ができない場合、または抽出後のフレームペイロードが明らかに不適切な場合に限り、一時停止した動画の直接シークを使用します。代替手段を使う場合は、そのトレードオフを説明し、固定ステージ、双方向、スムーズなスクロール動作は維持してください。
参考体験に合わせる
ユーザーからレイアウトやコピーについて追加の指示がない場合は、キャンバスのみのページを作成します。
- 白いページと、
100vw×100vhを覆う固定のオーバーフローヒドゥンなステージ。 - 意図的にスクラブできるだけの、見えないドキュメントの高さ。8 秒または約 240 フレームのソースなら、約
400vhが目安です。 - ナビゲーションバー、カード、見出し、行動喚起、グラデーション、または独自に作ったマーケティングコピーは配置しません。
- ステージ全体を覆い、
coverジオメトリを使って両軸の中央に配置し、各フレームを描画するキャンバス。 - 最初のフレームが読み込まれてから短い不透明度のフェードインを行い、空白フレームが一瞬表示されるのを防ぎます。
- 映像に適した場合に限り、白い背景、わずかなコントラスト調整、白背景の商品レンダリングに対する
mix-blend-mode: multiplyなど、控えめな画像処理を施します。
ユーザーがコンテンツを求めた場合は、簡潔に保ち、アニメーションの意図的な場面に重ねるか、その間に配置して、キャンバスの視覚的な存在感を損なわないようにします。ネイティブのキャンバスとブラウザー API で十分な場合、アニメーションの依存関係を追加しないでください。
キャンバススクラブを実装する
aria-hidden キャンバスを含む固定またはスティッキーなステージを使います。描画バッファーのサイズはデバイスピクセル比に合わせ、上限を約 2 にしつつ、描画時の寸法は CSS ピクセルで扱います。リサイズ時は、新しい DPR スケールを適用する前にキャンバスの変換をリセットし、スケーリングが累積しないようにします。
クランプしたページ全体の進行度をシーケンス全体に割り当てます。
const range = document.documentElement.scrollHeight - innerHeight
const progress = range > 0 ? Math.min(1, Math.max(0, scrollY / range)) : 0
targetFrame = progress * (frameCount - 1)
下方向へのスクロールでアニメーションを進め、上方向へのスクロールで逆再生します。スクロールとリサイズのハンドラーでは、低コストな測定値またはターゲットのみを更新します。単一の requestAnimationFrame ループを実行し、フレームレートに依存しない指数補間で浮動小数点のプレイヘッドをスムーズに動かします。
const dt = Math.min((now - lastTime) / 1000, 0.1)
const alpha = 1 - Math.exp(-dt * 9)
currentFrame += (targetFrame - currentFrame) * alpha
プレイヘッドの両側にある整数フレームを描画し、小数部分に応じて次のフレームをクロスフェードします。まずキャンバスの背景をクリアまたは塗りつぶし、描画後に globalAlpha をリセットし、リサイズ時には再描画します。
フレームを段階的に読み込む
シーケンス全体の読み込みが初回描画を妨げないようにします。
- まずフレーム 1 を読み込み、描画して、キャンバスを表示します。
- タイムライン全体に均等に分散したフレームを、たとえば 8 フレームごとにキューへ追加し、早い段階からシーク先の近くに代替フレームを用意します。
- 残りのフレームをすべてキューへ追加します。
優先読み込みと残りの読み込みで同じ画像を二度リクエストしないよう、リクエスト済みフレームと読み込み済みフレームを別々に管理します。リクエストしたフレームの読み込み中は、最も近い読み込み済みフレームを描画します。画像の読み込みに失敗しても、シーケンスの残りの処理が止まらないようにします。
プロジェクトのベースパスとデプロイ先に対応したアセット URL の方式を使います。所有するコンポーネントのアンマウント時に、スクロール、リサイズ、メディアクエリのリスナー、オブザーバー、アニメーションフレームをクリーンアップします。
レスポンシブ動作とアクセシビリティ
狭い画面でも cover による表示を維持し、意図的なトリミングを許容してください。画像を歪ませないでください。重要な被写体の配置をデスクトップとモバイルのサイズで確認してください。表示内容を追加する場合は、モバイルのビューポートの変化とセーフエリアを考慮してください。
prefers-reduced-motion: reduce の場合は、スクラブを停止し、適切な最初のフレームを表示したままにしてください。ページコンテンツへのアクセスを維持し、スクロールを乗っ取らないでください。装飾用のキャンバスがスクリーンリーダーに重複したコンテンツを読み上げさせないようにしてください。
結果の確認
プロジェクトのチェックを実行し、可能であればブラウザーで結果を確認してください。以下を確認します。
- スクロール位置の先頭と末尾が、それぞれ抽出した最初と最後のフレームに到達すること。
- 前後のスクロールが途切れず、急なジャンプ、再生、ちらつき、キャンバスの表示抜けがないこと。
- フレームのリクエストが重複せず、フレームが見つからない場合や読み込みが遅い場合は、近くの読み込み済みフレームが代わりに使われること。
- デスクトップとモバイルのサイズで、カバー表示のトリミング、DPR に応じたサイズ変更、キャンバスの拡大縮小が正しく動作すること。
- モーションの低減が設定されている場合に静止フレームを表示し、コンポーネントのクリーンアップが完了すること。
- 生成されたシーケンスの枚数、寸法、順序、合計サイズが許容範囲内であること。
- 無関係なプロジェクトの動作に影響がないこと。
最後に、体験の概要、抽出したフレーム数とデータ量、実行したチェック、残っているソースメディアの制約をまとめてください。