mkt-hyperframe-talking-head-video-16-9
專用 16:9 (1920×1080) 橫向編輯器 — 輸入是一個已包含 voiceover.mp3、source.mp4 和 script.txt 的工作區資料夾,輸出則是在同一個資料夾中,完整建立好的 HyperFrames 預覽專案,可直接執行 npx hyperframes preview。
這是位於協調器 mkt-full-video-with-11-hyperframe-heygen-16-9 之下的操作層。協調器負責處理第一階段 (TTS) 和第二階段 (HeyGen 頭像) → 然後將資料夾移交給此技能來處理第三階段(轉錄、建立專案結構、檢查並預覽)。
此技能產生的內容
<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 # 每個場景一個檔案,無論場景數量 N 為多少
│ ├── scene-2.html # 由平行的 LLM 子代理編寫 (第三階段d)
│ ├── 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。 |
Slug = 工作區資料夾的基礎名稱 (無需推導)。所有腳本都在該資料夾內讀取/寫入。腳本接受 --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 ── 轉錄稿 + script.txt → scenes-outline.json (5 個場景)
│
▼
4. [可選的 CHECKPOINT] ── 使用者檢閱大綱 / 調整開場白、標題
│
▼
5. scaffold_project.py ── 寫入 scenes.json (完整架構),建立 sfx/、logos/、avatar.jpg、yt-lower-third.html
│
▼
6. 🔥 LLM 子代理分岔 🔥 ── 協調器在單一訊息中產生 N 個並行的通用
代理 (每個場景一個),每個代理根據
visual-plan.json + references/composition-patterns.md
編寫 compositions/scene-{num}.html。
不是 generate_compositions.py (Jinja2 產生器
已棄用 — 會收斂成 5 種原型,無法適應
場景特定的隱喻,且會破壞列表式 6+ 個場景的結構)。
│
▼
7. generate_root_index.py ── 寫入 index.html,包含幻燈片安裝座 (掛載 scene-{num}.html
適用於所有場景,無 kind→fs-lesson 映射)、
頭像框 (claude-orange #d97757 品牌邊框)、
GSAP 時間軸 (SPLIT↔PIP、呼吸、強擊、
PIP_EVENTS、混合鉤子縮放) + 6 個已接線的 SFX +
在根層級加入奶油紙 B-roll 圖片層 (全 1920×1080)
│
▼
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 個場景邊界:
| # | 類型 | 預設開場白線索 | 變體 |
|---|---|---|---|
| 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 (solution 通常最長) 權重為 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" }
]
CHECKPOINT — 印出大綱供使用者檢閱。使用者可以內聯編輯開場白/標題/變體,然後繼續。如果技能以 --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 下方三分之一 | assets/compositions/yt-lower-third.html | <workspace>/compositions/yt-lower-third.html | 訂閱橫幅安裝座,影片最後 3 秒 |
如果技能捆綁中缺少來源資產,則會無聲地回退到舊版工作區路徑 (workspace/assets/...)。如果兩者都找不到,則跳過該資產 (合成畫面會優雅降級 — 使用文字頭像代替標誌,沒有下方三分之一)。
步驟 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 代理 (每個場景一個),以便它們並行執行。每個子代理:
- 從
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 失敗列 | 當 name 匹配關鍵字時 (chatgpt/gpt → chatgpt.png;gemini/google → gemini.jpg),自動附加 ChatGPT/Gemini 標誌。 |
| Solution hero-orb / vault | 發光球體內部的品牌標誌 (預設 Claude)。 |
| CTA terminal-row | 預設無標誌。 |
如果 assets/logos/ 不存在,子代理會回退到文字頭像 (無閃爍)。
模式參考 (8 種原型,子代理選擇並調整)
協調器的 references/composition-patterns.md 提供了 8 種經過生產驗證的模式:
| 模式 | 最佳用途 | 內部動機 |
|---|---|---|
tier-row before-after | 鉤子對比 | 2 個層級行 (之前 玫瑰紅 + 之後 萊姆綠) 附帶字母和項目 |
chats-stack | 問題 / 失敗 / 編輯-重新產生示範 | 使用者行 + 2-3 個 AI 失敗行 + 斷鏈戳記 |
hero-orb + spec-trio | 解決方案 / 機制 / 中心寶庫 | 發光球體 + 任務圖示 + 3 個規格層級行 |
counter-row | 回顧 / 數字證明 | 大計數器 (從 → 到) + 客戶 + delta 標籤 |
comment-terminal | 行動呼籲 / "留言 X" | 層級字母 + macOS 終端機模擬 + 2 張禮物卡 |
stats-3card | 知識介紹 / 3 事實揭露 | 3 個登陸頁面風格的欄位,帶有 // LBL + 漸層數字 |
comparison-2col | "何時該用哪個" | 2 欄 Yes/Yes 晶片 |
image-slot | (已棄用 — 圖片位於根層級) | — |
子代理自由調整:例如,hero-orb → "vault + 5 個聊天輻條"、stats-3card → "two-clock-comparison"、comparison-2col → "3 層級車輛卡片"。模式文件提供骨架 (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)輔助函式 PIP_EVENTS陣列由來自 scenes.json 的每個場景的pip_events驅動- 「混合鉤子」視覺縮放策略作用於
.avatar-breathing:- HOOK 場景: 在場景持續時間內從 1.0 緩慢斜升到 1.10 (建立戲劇張力,
power2.in) - HOOK→BODY 轉換: 快照重置 1.10 → 1.0 (釋放張力,0.5s
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),以作為轉場信號
...