Communitygithub.com

プログラム動画生成スキル

HTML5 Canvas、SVG、Playwright、Python/NumPy 音声合成、FFmpeg を使って、決定論的な 60fps 1080p MP4 アニメーションビデオをコードから直接構築・レンダリングします。

プログラム動画生成スキル とは?

このスキルは、AI エージェントが「アニメーションビデオを作って」「コードから MP4 を生成して」「リリースレキャップや Wrapped 動画を作って」といったユーザーリクエストに応えるための完全なワークフローを提供します。従来の Remotion のようなボイラープレート不要で、単一の HTML5 Canvas/SVG ファイルと Python スクリプトから 60fps 1080p の MP4 動画を決定論的にレンダリングします。キーとなるのは「フレームインデックスを純粋関数として扱う `window.__setFrame`」、レンダリング前に8~12枚の静止画をコンタクトシートにまとめてマルチモーダルで視覚的QAを行うループ、そしてWAV音声合成とFFmpegパイプを組み合わせた高効率なエンコードです。結果として、従来の壁時計ベースの録画方式(フレーム落ちやドリフトが発生)よりも高速で正確な動画生成が可能になります。Claude Code をはじめ、Cursor、Codex、OpenCode など幅広いAIエージェントプラットフォームで利用できます。

対応✓Claude Code✓Codex CLI✓Cursor✓Gemini CLI✓OpenCode
npx skills add https://github.com/jblxo/programmatic-video-skill/tree/HEAD/skills/programmatic-video

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

プログラム動画生成スキル は何をしますか?

AI コーディングエージェントが、単一の HTML5 Canvas/SVG ファイルと Python による手続き型オーディオスクリプト、ヘッドレス Playwright から FFmpeg パイプを通じて、60fps 1080p MP4 アニメーションビデオ を設計、視覚的に QA し、スコアリングし、レンダリングするための、決定論的でボイラープレート不要のワークフローです。

パスについて。 ${CLAUDE_SKILL_DIR} はこの SKILL.md を含むディレクトリです。Claude Code では自動的に展開されます。Cursor、Codex、OpenCode、その他のエージェントでは、${CLAUDE_SKILL_DIR} を skills/programmatic-video/ への解決済みパスに置き換えてください。


なぜ決定論的フレームステッピングなのか?

AI エージェントで動画を生成する際に、リアルタイムのブラウザ画面録画(MediaRecorder、requestAnimationFrame の壁時計キャプチャ、CSS トランジションのリアルタイム実行)を決して使用しないでください。

  1. 壁時計キャプチャはフレームを落とします。 CPU 負荷が高くなるとフレームをドロップし、音声と映像のドリフトやスタッターを引き起こします。
  2. CSS アニメーションは壁時計時間で動作します。 t = 14.20s の時点をシークして瞬時に視覚的な QA を行うことが不可能になります。
  3. ブラインドレンダリングは時間を無駄にします。 タイトルがカードからはみ出していないか確認する前に 5,000 フレームをレンダリングすると、作業が無駄になることが保証されています。

代わりに、このスキルで構築されるすべての動画は 3つのルール に従います。

  • ルール 1 — フレームインデックスの純粋関数: シーン全体は window.__setFrame(frameIndex, timeSeconds, fps) によって駆動されます。ここで t = frameIndex / fps です。すべての位置、不透明度、カウンター、パーティクルは、t の決定論的な数学関数です(Math.random() ではなく、mulberry32 のようなシード付き PRNG を使用)。
  • ルール 2 — フルレンダリング前のマルチモーダルコンタクトシート QA: フル 60fps MP4 をエンコードする前に、8~12 のキータイムスタンプをキャプチャし(render.mjs --timestamps ...)、それらを 1 つの contact-sheet.png(contact-sheet.py)に連結し、マルチモーダルの Read/View ツールを使用してその画像を検査し、テキストのクリッピング、オーバーラップ、低コントラストを修正します。
  • ルール 3 — サンプル精度のオーディオ + ゼロディスクブロート FFmpeg パイプ: マルチセグメントのステレオ WAV サウンドトラックとタイムスタンプ付き SFX キュー(synth-audio.py)を生成し、Playwright からの PNG バッファを ffmpeg -f image2pipe(render.mjs)に直接ストリーミングします。

エンドツーエンドエージェントワークフロー(6 ステップ)

ステップ 1: ストーリーボードとシーン予算

コードを書く前に、具体的なタイムラインテーブルを設計します。ビデオを 4~8 秒のシーンにグループ化し、scene.html と synth-audio.py の両方が共有する明示的なトランジションタイムスタンプ(T_cut)を設定します。

シーン時間 (t)フレーム (60fps)ビジュアルフォーカスオーディオ / SFX キュー
01 — フック / アラート0.0s – 7.0s0 – 420CRT ターミナル起動、タイプライターログ、2.7s の CTA ボタンクリックサブパルス + 2.7s の UI クリック/アンロックキュー、3.4s へのライザー
02 — ヒーローメトリクス7.0s – 15.0s420 – 9003D パースペクティブシンセウェーブグリッド + 3 つのスプリング物理カウンターカードフル 124 BPM シンセウェーブベース + 7.0s のステレオアルペジエータードロップ
03 — ディープテレメトリー15.0s – 23.0s900 – 1380分割画面プログレスバー + アニメーション半円ゲージフィルタースイープ + ハイハットドライブ、15.0s のサブインパクト
04 — ロールコール & フィナーレ23.0s – 30.0s1380 – 1800寄稿者カードのベントーグリッド + 「JOB'S DONE!」 バナー & 紙吹雪フィナーレコード + 25.2s のボイス/SFX キュー、28.5–30.0s のマスターフェードアウト

ステップ 2: window.__setFrame(f, t, fps) で scene.html を記述

HTML5 <canvas>(および/またはインライン <svg> + DOM オーバーレイ)を使用して、自己完結型の 1920x1080 HTML ファイルを記述し、以下を公開します。

window.__setFrame = function(frameIndex, timeSeconds, fps = 60) {
  if (window.__rafId) {
    cancelAnimationFrame(window.__rafId);
    window.__rafId = null;
  }
  const t = typeof timeSeconds === 'number' ? timeSeconds : frameIndex / fps;
  renderSceneAtTime(frameIndex, t);
};
  • 星、パーティクル、紙吹雪、ノイズのために、常にシード付き PRNG(mulberry32(seed))を含めて、フレーム f が実行間でビット単位で同一になるようにします。
  • document.fonts.ready を待ちます(render.mjs によって自動的に処理されます)。
  • コピー&ペースト可能なレシピ(3D パースペクティブグリッド、スプリングカウンター、CRT ターミナル、ゲージ、ベントーカード、紙吹雪物理)については、references/visual-patterns.md を参照してください。

ステップ 3: 高速タイムスタンプスナップショットの実行 & contact-sheet.png の構築

決して最初にフル 60fps レンダリングを実行しないでください。シーンごとに 1~2 のタイムスタンプ(およびトランジション中間点)をサンプリングし、単一のコンタクトシートを構築します。

# 1. 約3秒で9つのキーフレーム PNG をキャプチャ
node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --timestamps 1.8,3.0,5.2,8.5,12.5,16.5,20.5,24.5,28.0 \
  --out-dir ./qa-frames

# 2. それらをラベル付きグリッド画像に連結
python3 "${CLAUDE_SKILL_DIR}/scripts/contact-sheet.py" \
  --dir ./qa-frames \
  --cols 3 \
  --thumb-width 560 \
  --title "ビジュアル QA コンタクトシート" \
  --out ./contact-sheet.png

ステップ 4: マルチモーダル自己レビューループ(必須!)

画像 Read / View ツールを ./contact-sheet.png(および高密度に見える個々の ./qa-frames/t-*.png)に対して呼び出します。すべてのタイルを references/visual-qa-loop.md のチェックリストと照らし合わせて確認します。

  • テキストがカードの境界線、バッジ、プログレスバーからはみ出したり、衝突したりしていませんか?
  • すべての数字、ラベル、HUD ヘッダーは 1080p で高コントラストで読みやすいですか?
  • すべてのシーントランジションは、意図しない空/黒フレームなしで、きれいに着地しましたか?

contact-sheet.png で問題を見つけた場合は、scene.html を修正し、次のステップに進む前にステップ 3 を再実行してください。

ステップ 5: 手続き型サウンドトラックの合成 & WAV SFX キューのミックス

scene.html の正確なタイムスタンプに一致するトランジションライザーと SFX キューを持つ、ステレオ 44.1 kHz WAV サウンドトラックを生成します。

python3 "${CLAUDE_SKILL_DIR}/scripts/synth-audio.py" \
  --duration 30.0 \
  --bpm 124 \
  --style synthwave \
  --transitions 3.4,7.0,15.0,23.0,25.2 \
  --cue "25.2:./sfx/jobs-done.wav:+1.5" \
  --out ./soundtrack.wav

カスタムのマルチセグメントコンポジションやテーマ別サウンドパック(jblxo/claude-code-sound-packs など)の統合については、references/audio-synthesis.md を参照してください。

ステップ 6: FFmpeg パイプを介した最終 60fps H.264 MP4 のレンダリング

ビジュアル QA とオーディオ合成に合格したら、フルパイプモードで render.mjs を実行します。

node "${CLAUDE_SKILL_DIR}/scripts/render.mjs" \
  --html ./scene.html \
  --duration 30 \
  --fps 60 \
  --audio ./soundtrack.wav \
  --crf 18 \
  --out ./final-video.mp4

出力コンテナを ffprobe で確認します。

ffprobe -v error -show_entries format=duration,size:stream=codec_name,width,height,r_frame_rate -of default=noprint_wrappers=1 ./final-video.mp4

リファレンスプレイブック(オンデマンドでロード)

トピックリファレンスファイル
Canvas/SVG ビジュアルプリミティブ、イージング関数、シード付き PRNG、3D シンセウェーブグリッド、ゲージ、ベントーカードreferences/visual-patterns.md
マルチモーダルコンタクトシート QA ループ、一般的なレイアウト欠陥、タイムスタンプ選択戦略references/visual-qa-loop.md
手続き型 Python/NumPy オーディオ合成、コード進行、ライザー、ダッキング、WAV SFX キュー ミキシングreferences/audio-synthesis.md

関連スキル