Motion Ad Studio(自我改善)
製作一段 20-40 秒的直式動態圖形廣告,達到資深動態設計師認可的水準:第 0 幀已開始移動、一個貫穿整部影片的載體物件、在半空中切斷的轉場且速度匹配,並且每一次點擊、落地、降落和呼嘯聲 都鎖定在一個口說詞語或一個音樂節拍上。這部影片是一個單一的 HTML 頁面(GSAP 時間軸 + 純時間函數)。它會以幀級精確度渲染成 MP4,並且在任何人觀看之前,腳本會先對其進行檢查。音效是從影片本身的事件清單中放置的,因此音訊同步是透過建構來保證,而非依靠聽覺。
每次執行:先閱讀 references/lessons.md 和 references/runs.md。最後務必完成回顧(第 13 步)。
只有當你將經驗教訓寫回時,這個技能才會進步。
0. 事前檢查(總是執行)
python scripts/preflight.py [--elevenlabs-mcp yes] # 如果你已連接 ElevenLabs 工具則傳入 yes
下方使用的路徑:scripts/...、references/... 和 templates/... 是相對於此技能資料夾的路徑($SKILLS/motion-ad-studio)。
$MOTIONMAXXING 是引擎資料夾($SKILLS/motionmaxxing;preflight 會印出它),而 $SEAM_GATE 是 preflight 找到的可選接縫閘門腳本(或傳遞 --seam-gate FILE)。
| 需求 | 原因 | 如果缺少 |
|---|---|---|
| motionmaxxing 引擎 (Apache-2.0) | render.mjs(影格 → MP4)、look.py 閘控、lint.mjs 設計 lint、runtime/vendor/gsap.min.js | 在此技能旁執行 git clone https://github.com/Tejashmakwana/motionmaxxing,或設定 MOTIONMAXXING |
| ffmpeg + ffprobe、Node 18+、Chrome/Chromium/Edge | 渲染、探測、混音 | 安裝;如果 Chrome 未自動找到則設定 CHROME_PATH |
| Python 3.9+ 搭配 numpy + Pillow | 節拍、合成背景音樂、混音、工作表 | pip install numpy pillow |
| faster-whisper(選用) | 用於詞語鎖定時間的詞語時間戳記 | pip install faster-whisper,或任何能提供詞語開始/結束時間的對齊工具 |
| 接縫閘門(選用) | 證明每個轉場的速度匹配 | HyperFrames motion-doctrine + patches/seam-gate-camera-overlap.patch |
| ElevenLabs(選用,建議使用) | 富有表現力的旁白、作曲、自訂音效 | 請參閱下一節 |
ElevenLabs 是選用的:通知使用者一次,絕不阻擋
如果 preflight 印出通知(沒有 API 金鑰且你沒有 ElevenLabs 工具),請以使用者的語言在一條簡短訊息中轉達給他們,並讓他們選擇:
- 連接:使用者新增
ELEVENLABS_API_KEY或連接 ElevenLabs MCP 伺服器。重新執行 preflight。 - 繼續:使用下方的無金鑰路徑建構完整的影片。在交貨說明中提及一次,ElevenLabs 可以提升旁白和音樂品質。不要在相同專案中再次詢問。 如果你無法提問(批次或非互動式執行),則在不使用的情況下繼續,並將建議放入 NOTE.md。
| 層級 | 使用 ElevenLabs | 不使用(仍可出貨) |
|---|---|---|
| 旁白 | 帶有情緒標籤的 TTS、2 次錄製、選擇一個 | 使用者自己的錄音(最佳)、或本地/OS TTS 導引聲音;或無旁白的音樂主導影片 |
| 音樂 | 根據影片長度生成的音樂,在回報點插入高潮 | scripts/synth_bed.py(程序化、精確節拍網格)、或使用者擁有權利的曲目 |
| SFX | 1-3 個主要音效樣本(鞭子、呼嘯聲、打字聲) | scripts/mix_events.py 在本地合成每個 SFX |
| 詞語時間 | 附時間戳記的語音轉文字(或 TTS 時間戳記) | scripts/words.py(本地 faster-whisper) |
詳細資訊、提示、費用和許可規則:references/audio-providers.md。
流程
-
工作區。
python scripts/new_film.py <project>複製單次拍攝套件、GSAP 執行環境和本地字型。 渲染未修改的示範之一個靜止影格以證明工具鏈:node $MOTIONMAXXING/scripts/render.mjs <project>/film/index.html --still 1.2,16.4 <project>/stills。 -
品牌套件。 從使用者取得官方標誌檔案,並將每個標誌裁切到其 Alpha 邊界框。如果載體將對接到標誌中,則測量子字形矩形。透過計算網站 CSS 中的
#hex數量來取得顏色,並將字型作為本地 woff2 取得(scripts/fetch_fonts.py)。使用該品牌實際使用的 CTA 渠道。永遠不要重新繪製或近似標誌:要求提供它。 -
一個想法 + 一個新風格。 只寫一個只有這個品牌才能拍攝的想法。遮蓋標誌測試:隱藏標誌後,影片仍應指向這個品牌。寫三個方向,刪除兩個,然後選擇一個與
references/runs.md最後一行不同的風格。 -
鉤子。 撰寫 3 個少於 12 個詞的變體(問題、否定、具體性、故事)並選擇一個。第 0 幀已經在運作和移動,鉤子在第 1 幀時已在螢幕上,並且沒有任何東西從黑色淡入。
-
旁白。 撰寫約每秒 2.5 個詞(30 秒 ≈ 70-75 個詞)。如果 TTS 支援情緒標籤,為每一行標記([好奇] [自信] [充滿活力] [俏皮] [溫暖])。生成或錄製它,修剪長停頓,使用
atempo≤ 1.1 配合長度,然後取得詞語時間:python scripts/words.py audio audio/vo.wav --lang <code>。 Whisper 只給你時間。字幕文字始終來自已批准的腳本。 -
音樂。 生成(長度 + BPM + "在 <回報秒數> 處插入高潮")、授權曲目、或執行
python scripts/synth_bed.py --bpm 120 --dur 32 --drop 15.8 --out audio/bed.wav。使用python scripts/beats.py audio/music.mp3 audio/beats.json取得網格(synth_bed 會寫入一個精確的.beats.json)。修剪音樂開頭,使高潮落在回報的 VO 詞語上:影片節拍 k = first_beat - trim + k * period。 -
STORYBOARD.md + ledger.json(
templates/one-take/有一個已填入的範例)。包括:- 頁面規格、想法和三個方向;
- 節奏表(伸展 / t / 能量 0-10 / 路線 / 音樂);
- 一個時間映射:每個事件以及其所鎖定的詞語
w(i)或節拍beat(k); - VO 和說明性資料清單;
- 分類帳:每個接縫一行(退出/進入軸 + 方向、切換時間)。
-
建構。 從套件(
references/one-take-kit.md)複製模式:- 時鐘
w(i)/we(i)/beat(k); - 每幀順序
tl.seek → PRE(攝影機、移動的錨點)→ 游標(讀取即時 DOM 矩形)→ UP(跟隨的 UI); - 關鍵幀 3D 攝影機和一個瞄準即時 DOM 矩形的游標引擎;
- 打字/文字/類別更新器作為 t 的純函數;
sfx()事件和源自攝影機的呼嘯聲。
渲染器需要的合約:
#main帶有data-composition-id="main" data-width data-height data-duration。window.__seek / __duration / __timelines / __events / __player / __ready / __playerReady / __renderReady。 蒙太奇風格的影片(分層場景、扁平 UI、標誌載體):references/montage-kit.md。 - 時鐘
-
查看它。 渲染 15-20 個靜止影格(
node $MOTIONMAXXING/scripts/render.mjs ... --still t1,t2,... stills),平鋪它們 (python scripts/sheet.py stills sheet.jpg 6 220)並執行一次視覺檢查:每個影格一行,然後是一個缺陷清單。 修正並重複 2-3 次。- 幾何真相(什麼在哪裡、可見、其透明度)來自
node scripts/probe.mjs index.html "t1,t2" "#a,#b"。 - 文字真相來自全解析度裁切:視覺會錯誤地將縮小的阿拉伯文和 CJK 誤讀為不存在的「錯字」。
- 幾何真相(什麼在哪裡、可見、其透明度)來自
-
接縫閘門(建議)。在 localhost 上提供影片資料夾服務,然後執行
node "$SEAM_GATE" verify --ledger ledger.json --url http://127.0.0.1:<port> --comp-url http://127.0.0.1:<port>/index.html。 目標是 0 FAIL。單次拍攝攝影機甩動使兩個視窗都保持在螢幕上的行需要"overlap": "camera"加上patches/中的修補程式。之後停止伺服器。請參閱references/qa-gates.md。 -
混音。 每個 SFX 都存在於
window.__events中({t, type:'sfx', name, gain, dur?, speed?})。- 使用
node $MOTIONMAXXING/scripts/render.mjs index.html --still <t> ev轉儲它們,這將寫入ev/events.json。 - 混音:
python scripts/mix_events.py --events ev/events.json [--vo vo.wav --vo-at 0.10] [--music bed.wav --music-trim s] --dur <s> --out audio/mix.wav [--music-db -24] [--tp -2.5] [--whip/--whoosh/--typing samples] [--lift t0:t1:dB] [--fade t]。 - 音量:VO 為 -18 dBFS RMS,音樂為 -30 並在 VO 下方進行閃避,呼嘯聲峰值對齊到攝影機最快的影格,兩次 loudnorm 達到 -14 LUFS / TP ≤ -1。
- 使用
-
渲染 + 閘控 + 交付。
- 渲染:
node $MOTIONMAXXING/scripts/render.mjs index.html <NEW-name>.mp4 --audio ../audio/mix.wav --crf 17 --grain 0.03。每次嘗試使用一個新的輸出名稱:將兩次渲染導入同一個檔案會損壞它。 ffmpeg -v error -i x.mp4 -f null -必須不列印任何東西。然後執行python $MOTIONMAXXING/scripts/look.py x.mp4 --out look --expect <dur> --expect-audio(G0/G2/G3/G5 PASS)和node $MOTIONMAXXING/scripts/lint.mjs index.html。- 交付:9:16 母版、4:5 裁切(在檢查版面後執行
crop=1080:1350:0:200)、2-3 張封面 PNG、NOTE.md(想法、時間映射、真實與說明性資料、音訊來源 + 許可證、閘門編號、改進事項)和一個project/資料夾(影片 + 音訊 + 腳本)。 - 清理:停止伺服器和孤立的無頭 Chrome。
- 渲染:
-
回顧(強制性,在你最終回覆之前)。 將包含日期、規則和原因的經驗教訓附加到
references/lessons.md。新增一行到references/runs.md(日期、產品類型、風格、長度、閘門編號、已知時的結果)。如果某個步驟發生變化,請修補此檔案、腳本或套件。當使用者稍後反應時,記錄結果。經驗教訓只保留方法,絕不保留客戶名稱或私人資料。
品質標準
- 鉤子: 真實的客戶措辭或好奇心缺口。第 0 幀正在移動,鉤子在幀 1 時可讀,沒有從黑色淡入。
- 連續性: 一個貫穿影片的載體(游標、晶片、標誌標記),無交叉淡入淡出,並重複 2-3 種轉場類型。切斷發生在半空中且速度匹配。保持一個當前方向:對於「下一個」,RTL 影片將內容向左→右移動,LTR 影片向右→左移動。保留的向量用於表達意義。
- 時間鎖定: 每次點擊、掉落和落地都位於
w(i)或beat(k)上,並且音樂高潮位於一個 VO 詞語上。呼嘯聲源自攝影機速度。時間映射列出每個事件及其鎖定的內容。 - 無閒置搖晃: 每個停頓都帶有有目的的攝影機移動、階段性揭示或即時 UI。靜止只屬於回報點之前。
- 安全區域 (1080×1920):
- 付費 Meta 投放:可讀文字在 y 270-1250 和 x 60-960(右邊 120 像素是按鈕);
- 自然 Reels/TikTok:保持底部 320-370 像素清晰;
- 將字幕軌放在 UI 面板下方,永遠不要放在作曲家上方;
- 放下圖片已經顯示的單詞的軌道。
- 結尾: 字標加上該品牌實際渠道中的一個 CTA。保持結尾 0.6-1.4 秒,並保持最終鏡頭 ≤ 影片的 25%。
- 誠實: 在 NOTE.md 中宣告說明性資料。永遠不要虛構效能聲明、價格或推薦。
- 目標: look.py G0/G2/G3/G5 PASS、運動能量 ≥ 5/255 平均亮度變化(深色 UI 影片接近 2)、剪輯同步 ≥ 35%(測量的專業基準)、-14 LUFS ± 0.5 且真實峰值 ≤ -1 dBTP、0 解碼錯誤。
平台注意事項
- 在 Windows git-bash 上的背景作業:呼叫
node.exe,而不是nodewinpty 別名(「stdin is not a tty」)。 - 對 Windows 絕對路徑的 ESM 匯入需要
file:///C:/...。 - 無頭 Chrome 會從中斷的執行中洩漏。在最後,列出以
--headless=new和--remote-debugging-port=0啟動且其父進程已消失的瀏覽器,並殺死其根進程及樹狀結構。 - 渲染速度:在 1080×1920 下,扁平 UI 約為每 35 秒 4 分鐘。3D 世界約為 4-5 分鐘,每秒約 4 幀,但僅在 3D 圖層數量保持較小時。
檔案
scripts/:preflight.py:相依性和 ElevenLabs 通知;new_film.py:支架專案;fetch_fonts.py:本地 woff2;words.py:詞語時間;beats.py:節拍網格和高潮;synth_bed.py:無金鑰音樂;mix_events.py:事件驅動混音;sheet.py:聯絡表;probe.mjs:即時幾何。
templates/one-take/:完整的單次拍攝 3D 攝影機影片作為可執行示範(虛構產品、阿拉伯語 RTL 文案),包含 STORYBOARD.md 和 ledger.json。references/:research.md:環境調查、上游技能、安全注意事項、平台規格;lessons.md、runs.md:自我學習記憶;audio-providers.md、one-take-kit.md、montage-kit.md、qa-gates.md。
patches/seam-gate-camera-overlap.patch:可選的接縫閘門規則,用於單次拍攝攝影機影片。