mkt-hyperframe-talking-head-video-16-9
専用の 16:9 (1920×1080) ランドスケープエディター — 入力は voiceover.mp3 + source.mp4 + script.txt が既に存在する1つのワークスペースフォルダーで、出力はその同じフォルダーに npx hyperframes preview を実行する準備が整ったHyperFramesプレビュープロジェクトが完全にスキャフォールドされた状態になります。
これはオーケストレーター mkt-full-video-with-11-hyperframe-heygen-16-9 配下の 運用レイヤー です。オーケストレーターはフェーズ1(TTS)+ フェーズ2(HeyGenアバター)を処理し、フェーズ3(文字起こし + スキャフォールド + リンター + プレビュー)のためにフォルダーをこのスキルにハンドオフします。
このスキルが生成するもの
<workspace_folder>/
├── voiceover.mp3 # 入力(そのまま)
├── source.mp4 # 入力(HeyGenアバターのリップシンク、そのまま)
├── script.txt # 入力(そのまま)
├── transcript.json # 生成 — Whisperの単語レベル出力
├── transcript-cleaned.json # 生成 — ベトナム語タイポ修正済み
├── scenes-outline.json # 生成 — チェックポイント前のアウトライン(5シーン)
├── scenes.json # 生成 — シーンごとの最終メタデータ
├── index.html # 生成 — ルートコンポジション 1920×1080
├── compositions/
│ ├── scene-1.html # シーンごとに1ファイル、Nに関わらず
│ ├── scene-2.html # 並列LLMサブエージェントによって作成(フェーズ3d)
│ ├── scene-3.html # Pythonテンプレートによる生成ではありません(非推奨)
│ ├── ...
│ └── scene-N.html
├── sfx/ # スキルアセットからの6つのSFX(シンボリックリンク/コピー)
│ ├── camera-flash.mp3
│ ├── Whoosh sound effect (1).mp3
│ ├── búng tay.mp3
│ ├── Laser.mp3
│ ├── ting.mp3
│ └── Discord Notification - Sound Effect.mp3
└── (オプション) infographics/
├── 1.png 2.png 3.png # --with-infographics が指定された場合
└── prompts.md # シーンごとのクリームペーパー編集用プロンプト
キャンバス:
- ルート:
data-width="1920" data-height="1080"。 - アバターフレームデフォルトSPLIT:
top:100, left:1290, width:540, height:880, borderRadius:32。 - アバターフレームPIPコーナー:
top:600, left:1540, width:320, height:420, borderRadius:20。 - スライドマウント:
1200×1080SPLIT、PIP中は1920×1080にアニメーション可能。 - 各コンポジションの固有サイズ:
data-width="1200" data-height="1080"(マウントの100%を埋め、マウントが広がると拡大)。
必要な入力(ワークスペースフォルダー規約)
| ファイル | 必須 | 備考 |
|---|---|---|
voiceover.mp3 | はい | ElevenLabs TTSの出力(Hoàngの声)。 |
source.mp4 | はい | HeyGenアバターのリップシンク。現在は9:16ポートレート — ランドスケープフレームでは object-fit: cover; object-position: center 25% を使用して適切にクロップします。詳細は references/source-mp4-cropping.md を参照。 |
script.txt | はい | voiceover.mp3 を生成したベトナム語スクリプト。タイポ修正とシーン見出しの導出に使用します。 |
scenes-outline.json | いいえ | ユーザーが5つのシーンを事前定義している場合、自動検出をスキップします。スキーマ: ステップ3を参照。 |
スラッグ = ワークスペースフォルダーのベース名(導出は不要)。すべてのスクリプトはそのフォルダー内で読み書きします。スクリプトは --workspace <path> フラグを受け入れ、デフォルトではCWDを使用します。
パイプライン(順次スクリプト呼び出し)
voiceover.mp3 + source.mp4 + script.txt
│
▼
1. transcribe_audio.py ── Whisper VN → transcript.json(単語レベル)
│
▼
2. clean_transcript.py ── Whisperアーティファクトを除去、VN辞書を適用
│
▼
3. detect_scenes.py ── transcript + script.txt → scenes-outline.json(5シーン)
│
▼
4. [オプション チェックポイント] ── ユーザーがアウトラインを確認/キッカー、見出しを編集
│
▼
5. scaffold_project.py ── scenes.json(完全スキーマ)を書き込み、sfx/ + logos/ + avatar.jpg + yt-lower-third.html を作成
│
▼
6. 🔥 LLM サブエージェント ファンアウト 🔥 ── オーケストレーターがN個の並列汎用
エージェント(シーンごとに1つ)を1つのメッセージで起動し、それぞれが
visual-plan.json + references/composition-patterns.md を基に
compositions/scene-{num}.html を作成します。
generate_compositions.py(Jinja2生成器
非推奨 — 5つのアーキタイプに縮退、シーン固有の
メタファーに適応できず、6シーン以上のリスト形式で破綻)。
│
▼
7. generate_root_index.py ── スライドマウント(ALLシーンの scene-{num}.html をマウント、
kind→fs-lesson マッピングなし)+
アバターフレーム(claude-orange #d97757 ブランドボーダー)+
GSAPタイムライン(SPLIT↔PIP、ブリージング、パンチイン、
PIP_EVENTS、ハイブリッドフックズーム)+6つのSFXワイヤリング+
ルート(フル1920×1080)のクリームペーパーb-roll画像レイヤーを含む
index.html を書き込みます
│
▼
8. [オプション] scaffold_infographic_slots.py
── <img onerror> プレースホルダーを追加し、prompts.md を書き込み
(シーンのメタファーごとのクリームペーパー編集用)
│
▼
9. lint_and_preview.py ── npx hyperframes lint → エラー0、その後プレビュー
│
▼
ハンドオフ — Studio URL が表示され、ユーザーが確認し、オーケストレーターがレンダリングを決定します。
プレビュー優先ルール(譲れません): スキルはステップ9でStudio URLを表示して終了します。MP4レンダリングはユーザーの明示的な確認後にのみ実行されます — そのステップはオーケストレーターまたはユーザーの手動操作に属します。
ステップ1: transcribe_audio.py
python3 scripts/transcribe_audio.py --workspace <folder>
既存のスキル mkt-ai-video-extract-srt-segment をローカルで利用可能な場合はラップし、そうでない場合は whisper CLIを直接使用します:
whisper voiceover.mp3 --model medium --language vi --word_timestamps True \
--output_format json --output_dir .
ベトナム語音声には 決して --model medium.en を使用しないでください — .en は文字起こしではなく翻訳を行います。常に --language vi を使用してください。
出力: transcript.json — {text, start, end} 形式の単語レベルエントリの配列。
ステップ2: clean_transcript.py
兄弟の9:16エディター(mkt-hyperframe-talking-head-video/scripts/clean_transcript.py)からロジックを再利用します。U+FFFDを除去し、VN単語レベルおよびフレーズレベルの辞書(alphabit→Alphabet、Cod→Codeなど)を適用し、3〜5単語のフレーズにグループ化します。出力: transcript-cleaned.json。(caption-groups.jsonはありません — 16:9ではキャプションはオフです。)
ステップ3: detect_scenes.py
transcript-cleaned.json + script.txt を読み取り、標準的な知識動画の骨格を使用して5つのシーン境界を推論します:
| # | Kind | デフォルトキッカーヒント | バリアント |
|---|---|---|---|
| 1 | hook | スクリプトの最初の文 | tier-row(kind=hook によるポストスタック風) |
| 2 | problem | スクリプトが「ChatGPT/AI cũ」「khó」「đứt mạch」「vấn đề」…に移行する箇所 | chats-stack |
| 3 | solution | スクリプトがツール/方法を紹介する箇所 | hero-orb |
| 4 | recap | スクリプトが数値結果を示す箇所(「X tiếng」「Y khách hàng」) | counter-row |
| 5 | cta | コメント/保存/フォローのトリガーを含む最後の文 | terminal-row |
スクリプトに明確な5つのパートがない場合、より少ない数(最低3)を出力し、ユーザーに警告します。ヒューリスティック: トランスクリプトを文境界で約5つのチャンクに分割し、シーン3(通常最も長い解決策)に1.5倍の重みを付けます。
出力 scenes-outline.json:
[
{ "num": 1, "kind": "hook", "start": 0.07, "end": 13.73, "kicker": "...", "heading": "...", "variant": "tier-row" },
{ "num": 2, "kind": "problem", "start": 13.73, "end": 27.37, "kicker": "...", "heading": "...", "variant": "chats-stack" },
{ "num": 3, "kind": "solution", "start": 27.37, "end": 47.75, "kicker": "...", "heading": "...", "variant": "hero-orb" },
{ "num": 4, "kind": "recap", "start": 47.75, "end": 53.80, "kicker": "...", "heading": "...", "variant": "counter-row" },
{ "num": 5, "kind": "cta", "start": 53.80, "end": 60.68, "kicker": "...", "heading": "...", "variant": "terminal-row" }
]
チェックポイント — アウトラインを表示し、ユーザーが確認できるようにします。ユーザーはキッカー/見出し/バリアントをインライン編集してから続行できます。スキルが --auto(オーケストレーターモード)で呼び出された場合はチェックポイントをスキップします。
ステップ4: scaffold_project.py
scenes-outline.json を読み取り、各シーンを以下の情報でエンリッチします:
accent_words— 見出しから派生(数値 + 最後の2〜3の名詞を抽出)content— パターン固有のスキーマ(assets/templates/を参照)badges— シーンごとに1〜3つのフローティングバッジbrollEnd、hasBreath— SPLIT↔PIPスケジューリング用pip_events— シーン内のaccent_wordsタイミングから派生
scenes.json を書き込みます。また、スキルにバンドルされた assets/ から以下の自己完結型アセットをワークスペースに自動コピーします:
| アセット | ソース | 宛先 | 目的 |
|---|---|---|---|
| 6つのSFXファイル | assets/sfx/ | <workspace>/sfx/ | ビート音(camera-flash、whoosh、búng-tay、Laser、ting、Discord-notification) |
| ブランドロゴ | assets/logos/{chatgpt,gemini,claude,claude-code}.{png,jpg} | <workspace>/assets/logos/ | コンポジションに自動添付(chats-stackアバター、hero-orb、tier-rowツールバッジ) |
| アバター | assets/avatar.jpg | <workspace>/assets/avatar.jpg | yt-lower-third購読バナーのチャンネルサムネイル |
| YT lower-third | assets/compositions/yt-lower-third.html | <workspace>/compositions/yt-lower-third.html | 購読バナーマウント、動画の最後の3秒間 |
スキルバンドルにソースアセットがない場合、静かにレガシーワークスペースパス(workspace/assets/...)にフォールバックします。どちらにも見つからない場合、そのアセットはスキップされます(コンポジションはグレースフルデグラデーション — ロゴの代わりにテキストアバター、lower-thirdなし)。
ステップ5: 🔥 LLM サブエージェント ファンアウト(コンポジション作成) 🔥
generate_compositions.py は非推奨です。 呼び出さないでください。PythonのJinja2生成器はすべてのシーンを5つの固定アーキタイプ(hook→tier-row、problem→chats-stack、solution→hero-orb、recap→counter-row、cta→terminal-row)のいずれかに縮退させ、シーン固有のメタファー(例:「scroll-tape-wasted」、「two-clock-comparison」、「right-tool-vehicles」)に適応できず、6シーン以上のリスト形式(複数の tip-N が同じファイル名に縮退→上書き)で破綻します。
正規の方法: オーケストレーター(またはユーザー)が 単一メッセージ で N個の並列 general-purpose エージェント(シーンごとに1つ)を起動し、それらが同時に実行されるようにします。各サブエージェント:
visual-plan.json(パス:<workspace>/visual-plan.json、シーンインデックスnum-1)から自身のシーンブロックを読み取ります- オーケストレータースキルのリファレンス:
references/composition-patterns.md(8つのプロダクション実績パターン)、references/slide-design-tokens.md(パレット + タイポグラフィ)を読み取ります - そのシーンのメタファーに適したパターンを選択し、自由に適応します(hero-orb は vault+spokes に、stats-3card は two-clock-comparison になり得ます)
compositions/scene-{num}.htmlをスクラッチから以下の状態で作成します: 1200×1080 ビューポート、[data-composition-id="scene-{num}"]によるスコープ付きCSS、window.__timelines["scene-{num}"]に登録されたGSAPタイムライン、!importantなし、埋め込みimage-slotなし(クリームペーパー画像はルートレイヤーのみ)
結果: 各シーンは独自の、メタファーに適合したコンポジションファイルを取得します。衝突なし、退屈な5アーキタイプの固定化なし。
サブエージェントの完全なプロンプトテンプレートについては、オーケストレーターの mkt-full-video-with-11-hyperframe-heygen-16-9/SKILL.md ステップ4dを参照してください。
コンポジション内のブランドロゴ(サブエージェントはこれらを参照)
サブエージェントは、パターンが必要とする場合にブランドロゴを埋め込みます。ロゴは <workspace>/assets/logos/ にあります:
| パターン使用箇所 | ブランド要素 |
|---|---|
| Hook tier-row「after」 | tool-badge ピル(右上) — Claudeロゴ + 名前。 |
| Problem chats-stack 失敗行 | ChatGPT/Geminiロゴが、name がキーワードに一致した場合に自動添付されます(chatgpt/gpt → chatgpt.png; gemini/google → gemini.jpg)。 |
| Solution hero-orb / vault | オーブグロー内のブランドロゴ(デフォルトClaude)。 |
| CTA terminal-row | デフォルトではロゴなし。 |
assets/logos/ が存在しない場合(ちらつきなし)、サブエージェントはテキストアバターにフォールバックします。
パターンリファレンス(8つのアーキタイプ、サブエージェントが選択し適応)
オーケストレーターの references/composition-patterns.md には、8つのプロダクションでテストされたパターンが含まれています:
| パターン | 最適な用途 | 内部モチーフ |
|---|---|---|
tier-row before-after | フックのコントラスト | 文字 + アイテムを持つ2つのティア行(before rose/red + after lime/green) |
chats-stack | 問題 / 失敗 / Edit-Regenデモ | ユーザー行 + 2〜3のAI失敗行 + 破損チェーンスタンプ |
hero-orb + spec-trio | 解決策 / メカニズム / 中央保管庫 | 発光オーブ + タスクアイコン + 3つのスペックティア行 |
counter-row | まとめ / 数字の証明 | 大きなカウンター(FROM → TO)+ クライアント + デルタタグ |
comment-terminal | CTA / 「comment X」 | ティア文字 + macOSターミナルモック + 2枚のギフトカード |
stats-3card | 知識紹介 / 3つの事実の公開 | ランディングスタイルの3列、// LBL + グラデーション数字付き |
comparison-2col | 「どちらを使うべきか」 | 2列のYes/Yesチップ |
image-slot | (非推奨 — 画像はルートレイヤー) | — |
サブエージェントは自由に適応します: 例: hero-orb →「vault + 5 chat spokes」、stats-3card →「two-clock-comparison」、comparison-2col →「3-tier vehicle cards」。パターンドキュメントは骨格(HTML + CSS + GSAP)を提供し、LLMがクリエイティブな調整を行います。
ステップ6: generate_root_index.py
scenes.json + トランスクリプトからの total_duration を読み取り、assets/templates/index.html.j2 をレンダリングします:
- 1920×1080のルート、
#slide-bg、#heygen-bg、#avatar-frame > .avatar-breathing > .avatar-punch > #v-sourceを含む <audio id="a-source">は元のsource.mp4オーディオ(トラック1)を追跡- 6つの
<audio>SFXが絶対data-start(シーン境界)でワイヤリング - 左上のブランドマーク
- GSAPブロック:
- 初期エントランス(アバターフェードイン、ブランドフェードイン)
- SPLIT/PIP定数 +
goPIP(t)/goSplit(t)ヘルパー - scenes.json のシーンごとの
pip_eventsによって駆動されるPIP_EVENTS配列 .avatar-breathing上の 「ハイブリッドフック」ビジュアルズーム戦略:- HOOKシーン: シーン期間中に1.0 → 1.10 のスローランプ(ドラマ構築、
power2.in) - HOOK→BODYトランジション: 1.10 → 1.0 へのスナップリセット(緊張解放、0.5秒
power3.in) - BODYシーン(2..N-1)のPIP-INイベント時: 1.06 パンチビート(リズム、
power2.out→power3.out) - CTAシーン: 穏やかな1.0 → 1.04 プッシュ(クローズ、
sine.inOut)
- HOOKシーン: シーン期間中に1.0 → 1.10 のスローランプ(ドラマ構築、
- トランジション開始時の
.avatar-punch上のシーン開始毎の小さなパンチ(1.06)
…
[翻訳のために切り詰められています]