宣傳影片製作 (本機工具鏈)
與代理無關:專為任何能讀取檔案並執行 shell 命令的 AI 編碼代理所撰寫 — 透過 install.sh 原生安裝於 Claude Code、GitHub Copilot CLI / Microsoft Scout 及 Google Antigravity;亦可從 Cursor、Codex、Windsurf 及其他工具中作為純 Markdown 操作手冊使用。
此工具鏈首度由 Idan Shimon (Microsoft, github.com/idanshimon) 展示 — 他的一段 58 秒概念解釋影片,由 AI 代理在本機使用此技術棧以零成本製作,正是本技能的開發靈感來源。
請勿假設安裝位置:將 PROMO_VIDEO_SKILL_DIR 設定為包含此 SKILL.md 的目錄。其 scripts/ 目錄包含 TTS 腳本、縮寫發音輔助工具及固定的 TTS 依賴項;assets/ 目錄包含合成骨架、空間元件範本及決策日誌結構;references/ 目錄包含每台機器一次性的工具鏈啟動文件 (install.md)。
核心原則:腳本優先鎖定;後續的所有數字都必須從測量所得的旁白音檔推導,絕不憑空猜測。
宣傳,非解釋:此技能銷售的是「為什麼」— 對象、痛點、轉變、證明、一個行動呼籲。運作機制最多只能佔一個節拍,且僅在使用者要求時才納入;關於教導某事物如何運作的請求,屬於配套的 explainer-video 技能範疇。
工具簡介
| 工具 | 位置 | 已驗證版本 | 授權 | 角色 | 呼叫方式 |
|---|---|---|---|---|---|
| OpenMontage | ~/OpenMontage | 2026-07 檢出版本 | AGPLv3 (僅工具本身;影片中不包含任何其產出) | 管線治理:階段順序、決策日誌、閘門、渲染後自我審查紀律 | 閱讀其 AGENT_GUIDE.md + pipeline_defs/animation.yaml;你 (代理) 是編排者 — 無需執行任何守護行程 |
| Kokoro | PyPI | Kokoro-82M (hexgrad),kokoro==0.9.4 | 程式碼 Apache-2.0;模型權重 Apache-2.0 | 旁白 TTS,每個場景輸出 24 kHz 單聲道 WAV | Python 3.12 venv;KPipeline(lang_code="a"),語音 af_heart,speed 參數 |
| HyperFrames | ~/hyperframes | 0.7.57,從原始碼建置 | Apache 2.0 | HTML/CSS/GSAP 合成 → 透過無頭 Chrome 輸出確定性 MP4 | node ~/hyperframes/packages/cli/dist/cli.js <cmd> |
| FFmpeg | ~/FFmpeg 原始碼;建置目錄中的二進位檔 | git master (N-125608 時期) | GPL 建置 (啟用 libx264) | 音樂合成 (aevalsrc)、編碼、ffprobe 品質檢查、音量、平台封裝 | 將建置目錄置於 hyperframes 命令前的 PATH 中 |
| bun | npm 全域 | 1.3.14 | — | 建置 hyperframes 單一儲存庫 | npm i -g bun (brew cask 曾無聲失敗過一次) |
| Node.js | nvm | 24.x (需 ≥22) | — | 執行 hyperframes CLI | — |
| Python | uv 管理 | 3.12 | — | Kokoro 推論 | 務必使用 venv (uv venv --python 3.12 .venv);black + pylint 無錯誤 |
| espeak-ng | Homebrew 或 apt | 任何版本 | GPL | Kokoro G2P 後備方案 (必要) | macOS:brew install espeak-ng;Debian/Ubuntu:sudo apt install espeak-ng |
| gsap | 供應商檔案 | 3.x gsap.min.js | GSAP 標準授權 | 合成內的時間軸動畫 | 複製到 video/assets/ 中 — 絕不使用 CDN <script src> (離線確定性) |
環境檢查 (每台機器一次)
export FFMPEG_BUILD_DIR="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}"
export HYPERFRAMES_DIR="${HYPERFRAMES_DIR:-$HOME/hyperframes}"
export PATH="$FFMPEG_BUILD_DIR:$PATH"
node "$HYPERFRAMES_DIR/packages/cli/dist/cli.js" doctor
FFmpeg、FFprobe、Node 和 Chrome 必須全部通過才能進入正式製作階段 (其他 doctor 列出的項目為本技能未使用的可選元件)。如果其中任一項失敗,請遵循 $PROMO_VIDEO_SKILL_DIR/references/install.md — 完整的單機一次性啟動流程:系統套件 (macOS/Linux)、複製原始碼工具 (包括 OpenMontage 參考檢出)、從原始碼建置含 libx264 的 FFmpeg、建置 HyperFrames CLI,以及代理權限提示。當 doctor 已通過時,請勿載入該檔案。
Chrome:CLI 會自動使用 ~/.cache/puppeteer/ 下快取的 chrome-headless-shell (若無則下載一次)。首次 TTS 運行同樣會下載 Python 套件和 Kokoro-82M 權重。完成這些一次性下載後,合成、驗證、渲染和封裝流程即可離線執行。
專案結構 (每個影片建立一個,自有 git 儲存庫,原子提交)
<project>/
.venv/ # uv venv,python 3.12
.gitignore # .venv/ __pycache__/ video/snapshots/ .DS_Store
README.md # 製作方式 + 再現說明 (最後撰寫)
production/
research/research-brief.md # 附來源的事實 + 誠實的競爭對手比較表
proposal.md # 概念、場景清單、交付承諾、執行時間決策
script/script.md # 鎖定的旁白
scene_plan/scene-plan.md # 每個場景的視覺 + 動畫筆記
checkpoints/decision-log.json # 僅附加;(類別, 主題) 為鍵值
checkpoints/self-review.md # 渲染後證據
assets/audio/ # kokoro WAV 檔案 + durations.json
renders/ # 主版本 + 平台衍生版本
youtube/ # metadata.md + thumbnail.jpg
tools/tts_generate.py # 從此技能複製,編輯 SCENE_NARRATIONS
tools/tts_pronounce.py # 從 scripts/ 複製,縮寫發音 (請勿編輯)
tools/pronunciation.local.json # 可選的專案自訂發音詞典
video/
index.html # 主要合成檔案
assets/gsap.min.js # 供應商檔案
assets/audio/ # WAV 檔案複本 (相對於合成檔案的路徑)
階段 1 — 研究 (優先離線)
挖掘主題本身的儲存庫/README/文件 — 尋找成果和證據 (數字、採用率、前後對比結果),而非架構。產出 research-brief.md,內容包含:
- 定位區塊 (必要 — 腳本在鎖定前必須有此內容)。 每個項目一句話:對象 (此內容為誰而寫)、痛點 (他們目前感受到的困擾)、轉變 (對他們來說什麼改變了)、差異點 (選擇此方案的唯一理由)。這是核心訊息;後續每個階段都為此服務。
- 產品事實,每個都需對照來源驗證 — 僅保留那些能支持效益的項目 (通過「所以呢?」測試:觀眾能得到什麼?)。
- 競爭對手比較表 (弱點 → 主題如何應對)。誠實原則:坦承對手的真實優勢 (對手欄位中的一個 ✓ 可為你自己的主張增加可信度)。
- 一份 「腳本可用主張」清單。
階段 2 — 提案 + 決策
撰寫 proposal.md:重申定位區塊、5–7 個場景概念、目標約 60 秒、交付承諾 (以動畫為主,非投影片)、工具鏈表。記錄到 decision-log.json — 從 $PROMO_VIDEO_SKILL_DIR/assets/decision-log.json 的空結構開始 (欄位:category, subject, selected, options_considered, rejected_because, confidence):pipeline_selection、render_runtime_selection (記錄 Remotion 作為被考慮的替代方案 — OpenMontage 為硬性規定)、composition_mode (主要作品使用 atelier)、voice_selection、music_selection、output_profile、approval_gates 以及 cta_selection — 恰好一個行動呼籲 (為儲存庫加星號 / 安裝 / 觀看示範 / 造訪網站);宣傳影片若以功能列表而非請求作為結尾便會失敗。如果使用者的簡報已固定某個選擇,則標記為 approved_by: "user brief"。稍後更改了決策?附加一個新的條目,使用相同的 (category, subject) — 絕不編輯舊條目。
階段 3 — 腳本 (鎖定點)
約 150–155 字 ≈ 60 秒,使用 kokoro af_heart 語速 1.1。宣傳弧線 (銷售「為什麼」):利害關係/痛點鉤子 → 揭露 (名稱 + 其承諾的轉變) → 觀眾世界中的效益 → 證明 (誠實比較、真實成果) → 願景 → 來自決策日誌的單一行動呼籲。功能僅作為效益的證據出現:每個句子都必須通過「所以呢?」測試 (觀眾能得到什麼?),否則改寫。至多一個「運作機制」節拍,且僅在使用者要求時才納入 — 教導機制是 explainer-video 技能的職責。語氣:第二人稱、現在式、簡潔有力的句子 ("you ship faster",而非 "it enables faster shipping")。在腳本和螢幕文字中自然地書寫縮寫 ("OID", "MCP", "AI") — 在合成時,tools/tts_pronounce.py 會根據其詞彙庫推導出口語形式 (逐詞 vs 逐字母朗讀),未知的縮寫則會逐字母拼出並回報。在可選的 tools/pronunciation.local.json 中分類領域術語 ({"NASA": "word", "ECG": "letters", "NGINX": "engine X"})。避免全大寫強調:全大寫單詞會被視為縮寫。每個場景的字數預算 ≈ 其佔 60 秒的比例 × 2.55 字/秒。
階段 4 — 旁白 + 時間推導 (承重技巧)
從隨附的固定直接依賴項建立專案的 Python 3.12 環境,複製通用範本,然後僅編輯 SCENE_NARRATIONS:
uv venv --clear --python 3.12 .venv
uv pip install --python .venv/bin/python \
-r "$PROMO_VIDEO_SKILL_DIR/scripts/tts-requirements.txt"
mkdir -p tools
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_generate.py" tools/tts_generate.py
cp "$PROMO_VIDEO_SKILL_DIR/scripts/tts_pronounce.py" tools/tts_pronounce.py
PYTORCH_ENABLE_MPS_FALLBACK=1 .venv/bin/python tools/tts_generate.py
mkdir -p video/assets
curl -fL https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js \
-o video/assets/gsap.min.js
首次合成會下載 Kokoro-82M 權重 (~330 MB);後續運行使用快取,可離線執行。它會為每個場景寫入 WAV 檔案 + durations.json。如果運行時印出「未知縮寫」警告,請在 tools/pronunciation.local.json 中分類這些標記,然後在推導時間參數前重新執行。
將 150–155 字、語速 1.1 視為起始估算,而非校準基準。總時長 >62 秒?提高語速或刪減文字,然後再次測量。
推導時間軸 (場景間間隔約 0.3–0.5 秒):
n_start[0] = 0.5 # 開頭引導
scene_start[i] = n_start[i] - 0.15..0.4 # 視覺元素比旁白稍早出現
n_start[i+1] = n_start[i] + dur[i] + 0.3..0.35
TOTAL = last n_end + 0.6..0.9 tail (淡出至黑)
這些數字必須出現在三個地方並保持一致:場景的 data-start/ data-duration、<audio data-start> 值,以及 JS 中的 const S1..Sn 時間軸常數。將 WAV 檔案複製到 video/assets/audio/。
階段 5 — 背景音樂 (無需下載)
使用從原始碼建置的 FFmpeg 生成確定性的合成背景音墊。將 TOTAL_SECONDS 設定為推導出的合成總時長;無需任何外部樣本或私有參考:
TOTAL_SECONDS=60.5
FADE_SECONDS=3.5
FFMPEG_BIN="${FFMPEG_BUILD_DIR:-$HOME/ffbuild}/ffmpeg"
FADE_OUT_START="$(awk -v total="$TOTAL_SECONDS" -v fade="$FADE_SECONDS" \
'BEGIN { printf "%.3f", total - fade }')"
mkdir -p production/assets/audio
"$FFMPEG_BIN" -hide_banner -y \
-f lavfi \
-i "aevalsrc=0.07*(sin(2*PI*110*t)+0.65*sin(2*PI*110.7*t)+0.45*sin(2*PI*164.81*t)+0.30*sin(2*PI*220.9*t)):s=48000:d=${TOTAL_SECONDS}" \
-af "highpass=f=55,lowpass=f=1200,afade=t=in:st=0:d=2,afade=t=out:st=${FADE_OUT_START}:d=${FADE_SECONDS},pan=stereo|c0=c0|c1=c0" \
-c:a pcm_s16le production/assets/audio/music-bed.wav
保持稀疏;混音時設定 data-volume="0.12..0.16" 可營造氛圍 — 對於宣傳影片的能量感,請接近此範圍的上限,但絕不超過旁白音量。將 WAV 檔案複製到 video/assets/audio/ 並使用獨立的音軌。
階段 6 — 合成創作 (HyperFrames 合約)
從 $PROMO_VIDEO_SKILL_DIR/assets/composition-skeleton.html 開始 (它體現了以下所有規則);在撰寫 HTML 之前,先大致瀏覽 $HYPERFRAMES_DIR/skills/hyperframes-core/SKILL.md。
結構:獨立的 index.html,根元素 <div data-composition-id="X" data-start="0" data-duration="TOTAL" data-width="1920" data-height="1080">,場景為 <section class="clip" data-start data-duration data-track-index="1">,一個在 window.__timelines["X"] 同步註冊的 gsap.timeline({paused:true}),補間位置 = S<i> + local_offset。
以下是曾經耗費大量時間除錯的規則 — 請務必遵守:
- 每個
<video>/<audio>都需要一個明確且非空的id。 在 HyperFrames 中,沒有 id 的音訊可能在瀏覽器預覽中正常播放,但在渲染時會無聲 (lint 工具會發出錯誤;請勿忽略)。 - 絕不要在 CSS 中為 GSAP 補間的目標元素設定初始
transform:— 請使用tl.fromTo(el, {y:24, opacity:0}, {y:0, opacity:1, ...});GSAP 完全掌管 transform。(單獨設定opacity: 0在 CSS 中對於僅使用.to()的顯示動畫是沒問題的。) - 背景填充應放在一個全出血的子元素上 (
position:absolute; inset:0),絕不放在根元素上 (根元素的背景可能渲染為黑色)。 - 媒體元素是根元素的直接子元素,使用
data-track-index區分不同的音軌 (例如 7=旁白, 8=音樂)。 - 無無限重複 (
repeat: -1禁止 — 請使用有限次數,例如游標閃爍repeat: 9, yoyo: true),無Date.now/Math.random,無網路請求,無 CDN 腳本。 - 所有元素都需有唯一的
id;僅對 transforms/opacity 進行動畫 (加上strokeDashoffset用於 SVG 線條繪製)。 - 在中場出現的元素:隱藏初始狀態 + 在
S<i>+offset處進行補間。fromTo具有immediateRender屬性,因此在補間前進行時間軸搜尋會顯示 from 狀態 — 這正是使其搜尋安全的關鍵。 - 設計標記使用
:rootCSS 變數 = 主題;交換 ground/ink/accent + 字型堆疊即可重新換膚。使用渲染器捆綁的字型 (JetBrains Mono) — 系統字型無論如何都會被替換 (lint 資訊會告訴你對應關係)。 - 保持次要文字在背景色上符合 WCAG AA 標準 —
check命令會在對比度不足時失敗,並列印出可用的合規顏色。 - 有意的重疊/滾動超出:使用
data-layout-allow-overflow/-overlap/-occlusion標記,而不是留下未解釋的發現。
場景主題建議:展示結果狀態 — 觀眾世界的改善 (前/後對比、痛點消失、螢幕上的成果)。從主題的實際 UI/領域 (偽造的搜尋面板、終端機、樹狀圖、表格) 中提取輔助性的片段,作為效益的證據,而不是進行機制導覽。敘事弧線有範本;主題則不應受限。
$PROMO_VIDEO_SKILL_DIR/assets/composition-skeleton.html 包含範例場景和 GSAP 時間軸結構,可作為起點。