Communitygithub.com

brewed-ops/spatial-film

Spatial Film - 驅動 talking-explainer 的電影引擎。製作 45-90 秒無旁白空間 3D 產品動態圖形(單一 CSS-3D 相機、推鏡穿越、無硬切、最後一格循環回第一格),包含真實產品 UI、忠於平台的第三方畫布(GHL、n8n、Zapier)、原生節奏音樂與音效,透過 HyperFrames 以 1080p60 渲染。由 5 個平行場景工作者依單一合約(frame.md + 接縫表 + 每個場景的測試框架)協作完成。當使用者說「spatial film」或「3D motion graphic」、交出一份 MOTION-PROMPT.md,或要求 6 個以上場景 / 3D 相機的產品影片且無旁白時使用。含旁白的解說片(使用者語音和/或吉祥物現身解說)屬於 explainer-kit,它執行於此技能的機械之上。

spatial-film 是什麼?

此技能是一個專業 AI 代理技能,用於自動化 3D 產品影片製作,產生無旁白、拍攝風格的動態圖形,長度約 45 至 90 秒。它專為在複雜 UI 產品影片中達到高品質、流暢的 60fps 結果而設計,適合用於 Claude Code、Cursor、Codex 等平台,透過 HyperFrames CLI 工具在像 Windows 與 macOS 的系統上運作。此技能透過一個結構化的 6 階段工作流程來運作,從專案初始化(搭建)、腳本開發(腳本大綱、分鏡、設計合約、預渲染介面)到平行場景建置、音樂與音效整合、最終組裝、接縫檢查,以及 GPU 加速渲染。它強制執行嚴格的「硬性規則」,確保使用單一 3D 相機、從原始碼產生真實 UI,所有動畫使用彈性曲線,並確保無縫的場景接縫(每段接縫由鄰近兩個場景共享一個精確的畫面,且最後一格循環回第一格)。遇到常見問題時,此技能提供詳盡的疑難排解表,並包含內建自我測試以驗證環境設定是否正確。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/brewed-ops/talking-explainer/tree/main/skills/spatial-film

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

Spatial Film

已在一個 60 秒的產品影片(7 個場景,5 個工作者在一波中完成,每個接縫畫面精確,檢查乾淨, 1080p60 在 4 分 19 秒內)上驗證了端到端流程。範本的 film.json 中保存了該影片的真實場景時間條與提示表,作為工作範例。

<skill> = 此技能所在的資料夾(此 SKILL.md 所在的目錄)。每個腳本都從影片專案根目錄執行。 下面的 python 是指 explainer-kit 的設置檢查保存在 ~/.talking-explainer/config.json 中的 Python 指令 (Windows 上為 py -3.12,macOS 上為 python3)。

你需要什麼

  • Node 20+、ffmpeg + ffprobe 在 PATH 中、Python 3.10+ 並安裝 numpy 和 Pillow。
  • HyperFrames 技能:npx hyperframes skills update general-video hyperframes-animation media-use(封包 建構器、藍圖 + 動畫對應表、音樂輔助工具)。CLI 本身是根據專案固定版本,並透過 npx 執行。
  • 用於預渲染介面的 Playwright:在影片資料夾中執行 npm i -D playwright(或設定 PLAYWRIGHT_PATH)。
  • 可選,用於來源音樂:一個 HeyGen 帳號 - 在自己的終端機中執行一次 npx hyperframes auth login。 如果沒有,請自備音軌並從第 4 階段 music-analyze.py 開始。
  • 一台具有 GPU 能力的機器用於最終渲染(在軟體路徑上仍然可以渲染,但速度約慢 15 倍)。

如何在不浪費上下文的情況下使用此技能

  • 一次只載入一個階段的參考文件,在該階段開始時載入。切勿一次預載所有文件。
  • 腳本是經過驗證的程式碼。執行它們;切勿內聯重新產生它們的邏輯。
  • 主工作階段從不讀取整個場景檔案(20-60KB)。透過縮圖頁判斷場景;使用 grep -n 加上精確修補來修正。
  • 工作者會收到檔案路徑,而不是貼上的內容。storyboard.html(60KB+)是透過儲存格 ID 進行 grep,從不讀取整個檔案。
  • 先讀取縮圖頁;僅在檢查細節時才開啟單張快照 PNG。

階段(每個階段以一個閘門結束 - 在通過之前不要繼續)

#階段載入閘門
0搭建:node <skill>/scripts/new-film.mjs <dir> --name <slug>-資料夾包含 film.json、frame.md、kit、範本文件
1接收、BRIEF、STORYBOARD、草稿頁references/storyboard.md使用者在 ## Locked 下記錄的明確「go」
2frame.md、kit、預渲染介面references/surfaces.md(+ 僅當出現 GHL/n8n/Zapier 時才載入 platform-canvases.md)frame.md 中沒有 {{;每個捕捉 PNG 都已檢視過
3測試框架冒煙測試、封包、平行工作者references/workers.md每個場景:lint 0 錯誤、縮圖頁與其區塊相符
4音樂 + 音效(在工作人員建置時執行)references/audio.md音樂基底以原生 BPM 呈現,第 0 小節在強拍上;提示在 film.json 中
5組裝、檢查、接縫、渲染、交付references/verify-ship.md檢查通過、接縫檢查全部 PASS、硬體 GPU 渲染已驗證

路線經過 /hyperframes -> /general-video 以進行意圖和分鏡審查步驟(此技能提供 專案形狀、合約、腳本和閘門;general-video 提供封包建構器和工作者角色)。

檔案

路徑說明
template/專案骨架:film.json(場景時間條、BPM、背景音樂、音效、提示 - 唯一的時間來源)、frame.md(帶有填空的設計真實合約)、BRIEF.md、STORYBOARD.md、assets/kit.css(基礎影片 kit)、assets/fonts/(Poppins 500/700 + OFL)、references/worker-brief.md、references/scene-starter.html(lint 乾淨的場景骨架)、references/snippets.html、package.json(固定 hyperframes 0.8.117)。
surfaces/準備好的 GHL、n8n 和 Zapier 畫布 HTML 重建 + 一個長行銷頁面(虛構的 Northwind Dental 資料)、platform.css、sprite.svg、jobs.json。
scripts/new-film.mjs從範本搭建一個專案。
scripts/capture-surfaces.cjs將 src/captures/*.html 渲染為 assets/captures/*.png,2 倍大小(jobs.json)。
scripts/measure-surface.cjs1 倍大小的表面元素邊界框,用於精確註釋/裁切目標。
scripts/make-harness.py、scripts/test-scene.mjs每個場景隔離的測試專案;對一個場景進行 lint + 快照。
scripts/music-search.mjs、sfx-search.mjs透過 media-use 的 REST 輔助工具查詢 HeyGen 目錄(Windows 安全)。
scripts/music-analyze.py、music-bars.py僅需 numpy 的節奏 + 每小節能量分析(不需要 librosa)。
scripts/bgm-cut.py在小節線上剪輯背景音樂基底,拼接音軌自己的結尾、淡入淡出;--b 重複基底以在較長的影片下循環。
scripts/assemble.pyfilm.json -> index.html(場景時段在小節網格上、背景音樂、帶有持續時間 + 音軌的音效)。
scripts/seam-check.py像素級驗證每個接縫(剪輯前/時/後)和循環(第 0 幀 vs 最後一幀)。
scripts/render-final.mjs使用 --browser-gpu 的 CLI 渲染,記錄到檔案,驗證 gpu 模式 + ffprobe,接著執行 flash-scan.py。
scripts/flash-scan.py渲染的每一幀:一個與兩個相鄰幀都不同的幀(一個元素顯示了 1/60 秒)= 一個錯誤。
scripts/encode-web.mjs網路編碼(H.264 CRF 21、faststart、AAC 或 --silent)+ 海報幀。
scripts/blink-fit.py、scripts/build-presenter.py含旁白影片:眨眼疊加層用於姿勢頁面(--band = 眼睛區域);從其音軌的演示者疊加層,當吉祥物有 mouth-fit.json 時包含嘴型同步。
scripts/el-tts.py、el-words.py、el-music.py透過 ElevenLabs 的旁白影片(金鑰在環境變數 EL 中,絕不放在磁碟上):從 SCRIPT.md 取得語音候選、Scribe 文字時間、產生的背景音樂。
scripts/seam-diff.py接縫差異,遮蔽演示者方塊(含旁白影片)。
scripts/fromto-scan.py渲染前:標記 fromTo 中僅有的 FROM 屬性,這些屬性在渲染工作者(場景中段搜尋)時永遠不會被套用。每次渲染前必須為 0 個命中。
scripts/patch_exact.py精確、CRLF 安全的尋找/取代,用於腳本化的場景修復(斷言每個模式只有一個匹配)。
scripts/selftest.mjs端到端證明此技能在此機器上可正常運作。必須輸出 PASS。

含旁白的影片(一個語音旁白 + 一個螢幕上的演示者)

已在一個含旁白的「API vs Webhook」解說片(83 秒、垂直和橫向、克隆語音、吉祥物演示者、 10 個場景由 5 個工作者製作)上驗證。上述的音樂-影片規則仍然適用,除非被以下規則取代:

  • 先處理語音候選。 EL=<key> python <skill>/scripts/el-tts.py . eric=<voice_id> michelle=<voice_id> 讀取 SCRIPT.md 的縮排行,並為每個語音將一個 MP3 寫入 src/audio/voice-candidates/(金鑰僅從 環境變數取得,絕不放在磁碟上)。讓使用者透過聽覺挑選,然後僅轉錄挑選的語音。
  • 旁白就是時鐘。 文字時間:EL=<key> python <skill>/scripts/el-words.py <voice.mp3> src/timing/voice-words.json(ElevenLabs Scribe - 無本機模型,需要金鑰),或 使用帶有 word_timestamps 的 faster-whisper(設定語言,開啟 VAD;explainer-kit 的 transcribe.py,免費且本機)。將文字 JSON 保留在 src/timing/ 中。在 film.json 中設定 "bpm": 60, "beats_per_bar": 1,這樣一個「小節」就是 1 秒,場景 長度就是句子停頓處的普通秒數。分鏡區塊提供場景內部的文字時間;開始時間約早 0.1 秒,並在該字詞上著陸。在下一剪之前,給標題至少約 1 秒的螢幕時間(針對顯示台詞的最後一個字檢查剪輯點)。
  • film.json 額外項目(assemble.py + make-harness.py 會讀取它們):"audio": [{id, src, dur, volume}] 用於 語音,"overlays": [{id, track, z}] 用於一個全影片圖層(演示者),它位於每個場景之上,因此 它永遠不會在接縫處彈出,且場景保持無演示者狀態。
  • 演示者來自姿勢 PNG: 每個姿勢一個透明 PNG(explainer-kit 的 prep-mascot.py 修剪、 縮放並寫入清單),然後執行 scripts/blink-fit.py <mascot_dir>(可選,需要 torch;透過 NCC 將 BLINK 眼睛區域擬合到每個姿勢上;評分低於 0.70 的姿勢 不進行眨眼)和 scripts/build-presenter.py(從 src/presenter-track.json 寫入疊加層:姿勢在提示字詞上、 以頭部為錨點使切換永不跳動、語音包絡晃動、呼吸、眨眼、特效)。絕不手動編輯其輸出。
  • 音訊: 將語音 loudnorm 標準化至 -16 LUFS / -1.5 dBTP(一個在 +4.6 dBTP 限幅的普通增益),對其下方的背景音樂進行側鏈壓縮(離線,約低於語音 17 dB),音效輕柔(0.1-0.45)。填充語音金鑰,否則壓縮會將背景音樂截斷至語音長度(檢查是否警告「bgm 110.25s vs slot 113s」): [1:a]apad=whole_dur=<TOTAL>[k];[0:a][k]sidechaincompress=threshold=0.03:ratio=6:attack=25:release=450,atrim=end=<TOTAL>。 無目錄背景音樂(HeyGen 搜尋 500 秒或未登入):EL=<key> python <skill>/scripts/el-music.py .media/candidates/bed.mp3 <ms> "<提示:器樂、BPM、適合旁白下播放、無突兀音效、以解決和弦結束>" - 一條在影片長度時自行結束的音軌不需要拼接。
  • 接縫檢查噪音: 演示者在每個接縫處移動,因此 seam-check.py 僅因它而 FAIL。使用 scripts/seam-diff.py a.png b.png out.png x0,y0,x1,y1(遮蔽演示者方塊)判斷每個被標記的對 - 方塊外為 0.00% 即為通過。
  • 垂直(1080x1920)尺寸法則: 每個場景的頂部區域必須包含一個真實標題(60-84px),內文 >= 40px, 物件使用整個寬度和演示者上方的高度。第一批交付的影片在畫面上方 45% 的區域中使用了約 33px 的文字 - 在分派前將這些數字放入 frame.md 中,而不是之後。
  • 不是循環: 一個含旁白的影片以一個固定的鎖定畫面結束;忽略 seam-check 的循環行。

硬性規則(這些規則使它變得高級且流暢)

  1. 來源為真。 產品 UI 是從產品自己的 HTML/CSS 移植的;第三方畫布是從使用者的真實截圖重建的,絕不依靠記憶。僅使用虛構資料。僅使用產品真正擁有的功能。
  2. 單一相機。 每個場景中透視為 1866px(35mm);在相機圖層下有一個漂移圖層,使得沒有任何東西是靜止的;遠處葉片有視差 + 景深模糊。不要在 3D 父元素上使用 opacity/filter/overflow/clip-path(它會使其平面化)。
  3. 1080p+ 清晰。 使用 CSS zoom(.kit-zoom)縮放 UI,絕不使用 transform: scale(>1);每個元素以其在螢幕上最接近的大小創作;截圖是 2 倍 PNG,以原生大小或更小顯示。
  4. 60fps 流暢法則。 僅使用 transform/opacity;著陸使用彈性曲線,進場使用 expo/power3,相機移動使用 inOut;無 linear、steps、snap 或四捨五入;相機移動重疊 0.15-0.3 秒且持續 0.6 秒以上。
  5. 確定性。 每個場景一個暫停的時間線,最後註冊在 window.__timelines[id] 上,fromTo 使用明確的開始時間,無 random/clock/CSS 轉場。
  6. 接縫是共享的幀。 每個接縫是一個精確的畫面,由兩個相鄰場景各自持有約 0.1 秒,由一個在攝影機外的 2D 圖板鎖定。無硬切、無空幀、無淡出至無。最後一幀 = 第一幀。
  7. 在網格上。 場景是整/半小節;點擊、滴答聲、圖章和切換落在拍點上;音樂以其原生節奏在小節線上剪輯。
  8. 修復合約,而非修復場景。 根相對路徑 assets/...、id 永遠不以數字開頭、id 和 class 以場景 id 為前綴。每個場景都會違反的規則,在 frame.md / worker-brief 中修復一次。
  9. 禁止事項。 無表情符號、霓虹光暈、紫色到藍色漸層、彩色左邊框卡片、圓形載入動畫(shimmer)、庫存人物、「John Doe」、幻燈片節奏或毫無意義的動作。
  10. 從 CLI 使用硬體 GPU 進行最終渲染。 絕不使用 Studio 的匯出(軟體路徑,約慢 15 倍)。

問題排除

症狀原因修復
Lint:資產路徑錯誤子合成中的 ../assets/使用根相對路徑 assets/...(在合約中修復)
Lint:無效的合成 idid 以數字開頭使用 s01-click,而不是 01-click(film.py 拒絕它)
封包建構器拋出錯誤 / 封包 > 48KB兩個藍圖 id,或太多 rules:一個 id (Adapt);每個區塊 2-3 條規則
UI 看起來模糊被 transform 縮放或推向相機超過了創作大小使用 .kit-zoom,以最接近的大小創作
3D 突然變平在 3D 祖先上使用了 opacity/filter/overflow將其移動到葉子節點
接縫跳動其中一方未持有共享幀使用 seam-check.py,修復漂移方的圖板/姿勢
接縫 FAIL 幾個百分比但幀看起來相同圖板下方的 rig 複製體使陰影加倍僅在持有期間顯示圖板(frame.md 接縫)
產品 UI 偏離真實應用程式從記憶或不完整的 CSS 重建以 2 倍大小截取真實應用程式(surfaces.md 第一部分)
800+ 個 duplicate_audio_track 警告音效沒有 data-duration重新執行 assemble.py
music-search 說沒有憑證未登入使用者在自己的終端機中執行 npx hyperframes auth login
渲染很慢,約 1 幀/秒軟體 GPU(Studio 匯出)使用 render-final.mjs(CLI,--browser-gpu --workers 6)
渲染在停止後仍在執行停止 shell 並不會停止 node殺死行程樹(verify-ship.md)
沒有渲染進度可見輸出透過 `tail` 管道

自我測試

node <skill>/scripts/selftest.mjs

在一個暫存資料夾中搭建一個 2 場景的影片,然後執行測試框架、組裝、check、接縫檢查、一個硬體 GPU 渲染(1920x1080 @ 60 fps)以及網路編碼。它必須輸出 PASS - 在新機器上或任何編輯後執行它。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能