mcpField
F
frame-capture

frame-capture

github.com/moh4696クリエイティブ・メディア377221 回インストール5 日前に更新
リポジトリ

frame-capture について

frame-capture は、仮想クロックとフレームごとのスクリーンショットでウェブページを動画に記録するスキルです。スクロール演出を制御したい開発者や、重いシーンでも安定した出力を求める場面に適しています。

主な機能

  1. 01URLをMP4として記録
  2. 02スクロールとポインター動作の制御
  3. 03フレームごとの仮想クロック進行
  4. 04ChromiumまたはWebKitでの撮影
  5. 05ラベル付き動画比較の作成

活用シーン

  1. 01ページのスクロール演出の記録
  2. 02重いアニメーションシーンの録画
  3. 032つのページやモデル出力の比較

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/moh4696/open-3d-skills --skill frame-capture

インストール後、Claude Code で/frame-captureを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

agents/
openai.yaml
scripts/
compare.py
record.py
serve.py

詳細

フレームキャプチャ

画面レコーダーは、GPU がリアルタイムで描画できたものをそのままキャプチャするため、重いシーンではカクつき、スクロールの映像は手持ち撮影のようになります。このスキルでは別の方法で録画します。ページ自身のスクリプトが実行される前に、ページの時計を置き換えます。performance.now、Date.now、requestAnimationFrame は仮想時刻を読み取り、CSS アニメーションとトランジションもその時刻に固定されます。また、すべての <video> を一時停止し、その時刻にシークします。出力する各フレームで時計を正確に 1/60 秒進め、1 フレームを実行してスクリーンショットを撮ります。フレームのレンダリングに 2 秒かかっても、動画は常に完璧な 60 fps で再生されます。

ツール

スクリプト内容
scripts/record.pyスクロールキー、ポインターの動き、準備完了条件を指定して URL を MP4 に録画します
scripts/compare.py2 つのクリップをラベルと角丸パネル付きで上下に重ねる(または横に並べる)スクリプトです
scripts/serve.py動画のシークに対応する HTTP Range リクエストを処理する静的サーバーです

Python 3.9 以降、pip install playwright pillow、python3 -m playwright install chromium webkit、および PATH 上の ffmpeg が必要です。

実行

  1. scripts/serve.py でページを配信します。python3 -m http.server は使わないでください。 組み込みサーバーは Range リクエストを無視します。そのため、ブラウザーは配信された動画をシークできず(video.seekable が空になります)、録画した動画はすべて最初のフレームで止まります。record.py はこれを検出すると警告します。

    python3 scripts/serve.py path/to/site --port 8000
    
  2. まず高速なタイミング確認を行います。 1 秒あたり 10 フレームなら、数分ではなく数秒で動きの流れを確認できます。

    python3 scripts/record.py http://127.0.0.1:8000/ /tmp/check.mp4 --seconds 20 --fps 8 \
      --scroll "0:0 2.5:0 9:40% 12:40% 19:100%" --pointer drift
    

映像を確認し、キーを調整して、繰り返します。その後で初めて、クリップ全体をレンダリングします。

  1. 最終版をレンダリングします。 --size は CSS ビューポートのサイズで、--dpr はそれに乗算する値です。--size 1920x1080 --dpr 1 では 1080p になり、--size 1280x720 --dpr 1.5 では、より大きなレイアウトで同じ 1920x1080 になります。出力形式は H.264、CRF 16、yuv420p、BT.709 タグ、faststart で、音声はありません。

    python3 scripts/record.py http://127.0.0.1:8000/ out.mp4 --seconds 20 --fps 60 \
      --scroll "0:0 2.5:0 9:40% 12:40% 19:100%" --pointer drift --ready "window.__ready === true"
    
  2. 結果を確認してから引き渡します。重要なタイミングのフレームを取り出し(ffmpeg -ss 9 -i out.mp4 -frames:v 1 f.png)、確認してください。最初のフレーム、各スクロール停止時、最後のフレームを確認します。

動きの指定
  • --scroll のキーは seconds:position 形式です。位置にはピクセル数(1200)、スクロール範囲に対する割合(40%)、またはビューポートの高さに対する倍率(2.5vh)を指定します。区間はイージングされます(半分は線形、半分は smootherstep なので、長い移動でも中間で急加速しません)。線形の区間にするには、時刻の後に ~ を付けます(例:9~:60%)。
  • 視聴者に読ませたい内容があるときは、そこで止めます。固定表示されるセクションやカウンターには、位置が同じキーのペアを指定します。
  • --pointer drift は、実際のマウスを中心の周りでゆっくり円運動させるため、ホバー状態、視差効果、カーソル追従型の仕組みが動き出します。--pointer 0.7,0.3 ではその位置に留めます。
  • カメラ移動やツアーなど、ページ側が最適な動きを把握している場合は、ページに動きを制御させます。?record=1 フラグのもとで window.__recordFrame = (t) => { ... } を定義してください。各フレームの前に、仮想時刻が秒単位で渡されて呼び出されます。録画中は window.__recording が true になります。
  • スムーズスクロールライブラリは、スクロール位置を設定するレコーダーと競合します。--kill-lenis を指定すると、Lenis の読み込みを停止します。それ以外のライブラリは、?record=1 のときに無効にしてください。

ページを録画可能にする

  • 時刻は performance.now() または rAF のタイムスタンプから取得してください。setTimeout や setInterval は使わないでください。 時計が仮想時刻になっていても、タイマーは実時間で動きます。そのため、setTimeout(next, 3000) は実時間で 3 秒後に実行されますが、それが 20 フレーム目の場合も 400 フレーム目の場合もあります。ページの時計に基づいてスケジュールしてください。

    const pending = [];
    const later = (secs, fn) => pending.push({ at: performance.now() / 1000 + secs, fn });
    // in the frame loop:
    const now = performance.now() / 1000;
    for (let i = pending.length - 1; i >= 0; i--) if (now >= pending[i].at) pending.splice(i, 1)[0].fn();
    
  • 準備完了フラグ(最初のフレームのレンダリング、テクスチャのデコード、フォントの読み込みが済んだ後に window.__ready = true を設定)を公開し、--ready に渡してください。アセットの読み込みが完了する前に録画すると、フレーム 0 に読み込み中のちらつきが焼き付いてしまいます。

  • 録画モードでは、動画に映さない UI(ヒント、カーソル、ローダー、Cookie バー)を非表示にします。

  • WebGL のフレームが黒くなったり古いままになったりする場合は、録画時に preserveDrawingBuffer: true を指定してレンダラーを作成してください。

ブラウザー

  • **Chromium(デフォルト)**は、ヘッドレスで実際の GPU 上で WebGL を実行します。macOS ではスクリプトが --use-angle=metal を追加するため、フルスピードでレンダリングされます。これがないと Chromium は SwiftShader にフォールバックします。正しく動作しますが、何倍も遅くなります。
  • WebKit(--browser webkit)では、Safari のレンダリングを確認できます。フォントのスムージング、色の処理、動画のデコードが異なります。1080p ではスクリーンショットの取得がまれに停止します(約100回に1回)。スクリプトは再試行し、ステップ間で時計が一時停止しているため、再試行でも同じフレームが返されます。
  • Playwright 独自の Chromium が見つからない場合(アップグレード後のバージョン不一致など)、スクリプトは Playwright のキャッシュ内から最新の Chromium を探します。CHROME_PATH を設定すると、そちらが優先されます。
  • 表示中でも見ていないブラウザータブや、非表示の埋め込みプレビューペインでは、録画しないでください。バックグラウンドタブでは requestAnimationFrame が制限されたり、停止したりします。ヘッドレスではそのようなことはありません。

比較

python3 scripts/compare.py a.mp4 b.mp4 versus.mp4 --labels "Model A" "Model B"            # stacked, for phones
python3 scripts/compare.py a.mp4 b.mp4 versus.mp4 --labels "Before" "After" --layout side   # side by side

公平に比較するには、比較対象以外の条件をすべて同じにします。

  • ビューポート、長さ、動きを同じにします(--scroll のキーをそのまま再利用します)。
  • 各映像のコンテンツ部分を先に切り抜きます。比較するもう一方の映像にない透かし、ウェブカメラのオーバーレイ、UI の装飾を取り除きます。
  • 音声なしで出力します。2つのサウンドトラックがぶつかり、音声が映像への注意をそらします。
  • 短い方の映像は最後のフレームを保持し、両方が同時に終わるようにします。
  • ラベルには各映像を正直に記載します。視聴者に知られている方を上に配置します。

納品

  • ソーシャルプラットフォームではすべて再エンコードされます。1920x1080 または 1080x1920、60 fps、H.264、CRF 14~18 が最も画質を保てます。高解像度でも、多くの場合ダウンスケールされます。
  • マスターは保管しておきます。6秒のループや縦向きの切り抜きなどは、再録画せず、マスターから ffmpeg で作成します。
  • 録画後に音声を追加し、録画時に表示されたフレーム番号に合わせます。仮想時計を使って音声を録音しないでください。

コメント