Communitygithub.com

YahyaLendani/motionbrief

從 HTML 或 React 製作動態圖像與短片 — 標題卡、標誌動畫、動態字體、計數器、數據揭示、下三分之一、透明疊加、功能剪輯。將自然語言需求轉換為驗證過的簡報,然後渲染;將一份簡報批次轉換為多部影片。支援 HyperFrames(HTML + GSAP,固定版本,自動安裝一次,Apache 2.0)和 Remotion(React + TypeScript)。當被要求生成、動畫化、建構或渲染影片、動態圖形、動畫或疊加層時使用;用於製作發布影片、動畫標誌或卡片;在 Remotion 和 HyperFrames 之間移植組合;或修復感覺廉價、彈跳、緩慢或像滑動的動畫。

motionbrief 是什麼?

motionbrief 是一個 AI 助手技能,用於從 HTML 或 React 製作動態圖形與短片。它將使用者的自然語言需求(例如「製作一個 6 秒的商標動畫」)編譯成結構化的 `brief.json`,其中包含持續時間、尺寸、節拍、色彩配置等所有必要參數,然後生成相應的影片。該技能支援兩種渲染引擎:HyperFrames(基於 HTML + GSAP,Apache 2.0 授權,無團隊規模限制)和 Remotion(基於 React。該技能會根據使用者需求、現有程式碼庫和團隊規模自動選擇最佳方案。其核心是「簡報驅動」的工作流程,摒棄耗時的規範撰寫與審批環節,讓 AI 直接編譯需求、建構、驗證並渲染。它提供全面的驗證腳本,可檢查時間、文字可見性、字體加載、動畫流暢度等常見問題,確保產出的影片在視覺上具有專業感。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/YahyaLendani/motionbrief-claude-skills/tree/main/skills/motionbrief

在你喜歡的 AI 中提問

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

說明文件

動態圖形

透過撰寫渲染器逐幀搜尋的網頁來生成影片。 以下兩種方式做的是同一件事;差別在於你撰寫的內容。

  • HyperFrames — 一個 HTML 檔案,CSS 負責外觀,一個暫停的 GSAP 時間軸負責 動畫。node scripts/hf.mjs 會執行固定版本並從已提交的鎖定檔案安裝一次。 Apache 2.0。
  • Remotion — React 元件。useCurrentFrame() 返回當前影格,由你自行 計算數學。成熟、具型別,且僅供三人以下免費使用。

在撰寫組合程式碼之前,請載入對應的參考文件。框架規則無法猜測,且大多數失敗是無聲的: 一個從未註冊其時間軸的 HyperFrames 檔案,只會渲染出一個靜止畫面,且不會產生任何錯誤。


簡單路徑

使用者以任何詞彙描述他們想要的效果。他們永遠不需要撰寫簡報、規格或節拍表 — Claude 負責編譯。

/motion 一個為 Inkwell 製作的有力 6 秒商標動畫

這就是完整的輸入。背後執行的流程:

  1. 編譯 需求成 brief.json — 持續時間、尺寸、影格率、帶有時間的節拍、 逐字的文案、緩動、色板,以及一個 assumptions 列表。每個間隙都從 references/brief.md 中的表格取得預設值;沒有任何東西留空,也不對任何東西提出質疑。
  2. 顯示 精簡摘要(一個表格,約 12 行)並在同一次對話中建構。 沒有審批關卡。
  3. 從模板建構、驗證、渲染、檢視影格。

後續的迭代是修改欄位,而不是重建。「讓它更有力」會改變 feel.ease 和兩個持續時間;除非 kind 或 motion 改變,否則程式碼不會變動。

簡報是讓這個過程變得廉價的關鍵。它與組合程式碼一起存在於磁碟上, 因此修訂就是一個差異比較,而重新渲染只需要一個指令。


優先選擇路線

信號路線
全新建構,未指定框架HyperFrames
要重複使用現有的 HTML/CSS/GSAP/LottieHyperFrames
不需要 node_modules,不需要建構步驟HyperFrames
團隊人數超過三人HyperFrames(授權)
使用者指定 Remotion,或儲存庫是 React/TSRemotion
需要設計系統、圖表庫或複雜元件Remotion
移植現有的 Remotion 專案Remotion(移植成本大於節省的成本)

當使用者同時提及兩者時,使用 HyperFrames 建構,並用一行字說明 Remotion 移植 可應要求提供。除非要求比較,否則對同一個作品進行兩次完整建構是浪費工作。


循環

1. 編譯簡報

在撰寫程式碼之前將需求轉換為 brief.json。架構、 kind/motion 語法、預設值表格和迭代槓桿都存在於 references/brief.md 中。

node scripts/brief.mjs brief.json          # 驗證 + 摘要表格
node scripts/brief.mjs brief.json --json   # 機器結果

將摘要列印給使用者,修正任何 ERROR,然後在同一次對話中繼續進行。 警告是需要判斷的 — 你接受的警告會放入 assumptions。

簡報也承載了節奏。選擇 audio.bpm 使節拍網格能整除剪接點 — 在 bpm 下,一個節拍是 60 / bpm 秒,並且每個 beats[].start 都應該落在 一個節拍上。120 BPM 會產生每 0.5 秒一個節拍,並且適合大多數短片。如果 brief.mjs 回報 off_beat_grid,請移動剪接點或改變節奏;不要 忽略它,因為這就是一個感覺到位與感覺微妙地不對的作品之間的差別。

完成條件 brief.mjs 退出碼為 0,每個節拍都有一個時間視窗、一種類型、一個 動畫和逐字的文案,並且沒有剪接點偏離節拍網格。

2. 建立專案骨架

從此技能的模板開始,而不是從空白檔案開始 — 它們對於 兩個合約都是正確的,並省去兩個容易失敗的步驟(時間軸註冊、序列時序)。

# HyperFrames — 純 HTML。固定的引擎會自行安裝一次,這需要網路連線
cp -R assets/hyperframes/. ./my-video/
node scripts/hf.mjs lint ./my-video

# Remotion — React 專案,需要其固定的依賴項一次
cp -R assets/remotion/. ./my-video/
cd my-video && npm ci
# PowerShell
Copy-Item -Recurse -Force assets\hyperframes\* .\my-video\
Copy-Item -Recurse -Force assets\remotion\* .\my-video\

完成條件 node scripts/hf.mjs lint 通過,或 npx remotion compositions src/index.tsx 列出組合 ID。

3. 建構節拍

每個節拍一個檔案。保持時間軸扁平 — HyperFrames 中使用絕對時間,Remotion 中使用 <Sequence> 影格。當建構改變時序時更新節拍表,然後重新檢查總持續時間。

以節拍的名稱命名每個場景,因為這是檢查找到它們的方式: HyperFrames 宿主元素上的 data-brief-beat="<id>",Remotion 中的 <Sequence name="<id>">。如果 Remotion Sequence 自行計算時序,也在 其內部的元素上放置 data-brief-beat="<id>",以便可以測量時序。

完成條件 表中的每個節都存在於程式碼中,組合持續時間與 表匹配,並且沒有 TODOs、存根或佔位文案。

4. 驗證動畫

靜止畫面會誤導時序。先檢視影格,然後檢視渲染結果。

node scripts/check-contract.mjs --dir ./my-video --preflight   # 靜態,無需安裝
node scripts/check-contract.mjs --dir ./my-video --runtime     # 同時在瀏覽器中檢查

node scripts/hf.mjs check ./my-video                # 佈局、動畫、對比度
node scripts/hf.mjs snapshot ./my-video --review    # 節拍 + 接縫影格 PNG
node scripts/hf.mjs keyframes ./my-video --selector "#card" --shot motion.png

npx remotion still src/index.tsx LaunchCard out/f.png --frame=45
npx remotion studio src/index.tsx              # 以 1 倍速觀看

check-contract.mjs 可以在不安裝任何東西的情況下捕捉無聲的失敗:未註冊的 時間軸、不匹配的 window.__timelines 鍵、未暫停的 時間軸、缺少持續時間、組合中的 Math.random()、未夾緊的 interpolate。這是一個預檢,而不是真正檢查工具的替代品。

當 brief.json 位於專案中(或 --brief 指向一個),它也會 將建構結果與簡報進行比較。每個需求最終都會是 verified、failed 或 unverified。unverified 不是通過,並且會阻止渲染。

代碼狀態含義
brief_format_mismatchfailed寬度、高度、影格率或長度與 format 不同
brief_scene_count、brief_scene_unmappedfailed某個節拍沒有聲明其 ID 的場景,或者某個場景沒有對應的節拍。位置不等同於身份
brief_timing_mismatchfailed場景的開始或持續時間與簡報不符,誤差超過一個影格
brief_copy_missingfailed該行不在場景中。註解和未使用的變數不計入
brief_copy_wrong_scenefailed該行只在另一個場景中
copy_not_visiblefailed執行時期:在 DOM 中但被隱藏、透明、在畫面外、被裁剪、模糊或覆蓋
copy_hold_shortfailed執行時期:可讀取時間少於 beats[].hold
first_frame_emptyfailed執行時期:visibleAtStart 已設定,但節拍的內容完全沒有被繪製
first_frame_unverifiedunverified執行時期:第一影格只有圖形,或者節拍沒有文案。請檢視該影格
brief_timing_unverified、brief_format_unverifiedunverified來源計算出這些。執行時期可以解決
brief_copy_dynamic、brief_copy_unverifiedunverified是否顯示是一個執行時期的問題。在執行時期之前,Remotion 的文案始終是這個狀態

比對忽略大小寫和空白,並折疊彎曲引號。其他標點符號是 重要的,並且 "12,480" 會匹配一個穩定在 12480 的計數器。當需求保持 unverified 時,指出哪些,並嘗試在接受它們之前使它們可被測量。接受一個需求意味著命名它,使用 --allow-unverified "beat.lines.copy[0].visible",並向使用者報告。不要 接受通用的模式,並且失敗的結果根本無法被接受。請閱讀 references/validation.md 以了解確切的規則和限制。

修正程式碼中的偏差,或者有目的地更改簡報並重新執行 brief.mjs — 永遠不要讓兩者不一致。

審閱影格 — 所有檢查都可能通過,但影片卻是有問題的

通過合約檢查表示時間和文案匹配,並且文字是可讀的。它 沒有說明色板、緩動、轉場,或影片是否運作正常。此技能自己的模板通過了 lint、佈局、 動畫、對比度和工藝檢查,但它在每個節拍處切換到黑色畫面,並且在計數器 數字落地的瞬間就退出了計數器效果。只有檢視影格才發現了這個問題。捕捉它們:

# HyperFrames:節拍影格、每個剪接點周圍的 5 影格條、以及手機螢幕截圖
node scripts/motion-render.mjs --brief ./my-video/brief.json --snapshot --no-render

# Remotion:對於每個剪接點 c(以影格為單位),抓取 c-6、c 和 c+6,加上每個節拍的中間
#(模板在 75、210 和 270 影格處剪接)
node scripts/motion-render.mjs --dir ./my-video --no-render \
  --stills 37,69,75,81,142,204,210,216,240,264,270,276,315

然後閱讀圖片並回答每個問題。修正程式碼,重新捕捉,再次檢視:

  • 剪接點是黑色的嗎? 剪接點周圍有超過一個空白影格表示退場 過早完成,下一個節拍從無到有淡入。移動退場使其 在剪接點結束(start = beat duration − exit duration)。
  • 重點畫面停留時間足夠嗎? 計數器的最終數字,或一行文字的最後一個詞, 在螢幕上靜止至少一個節拍(60 / bpm 秒),然後才離開。 在它剛出現的瞬間就退場,意味著它從未被讀取。
  • 在手機上看起來如何? 檢查 review-phone.jpg,或者想像影格在 寬度 360 px 時的樣子。在 1080p 解析度下,大約小於 40 px 的標籤和標語通常會失敗。
  • 這是簡報指定的字體嗎? 如果顯示的是替代字體(如 Segoe UI 或 Arial),表示該字體 從未載入成功,另一台機器將渲染出不同的影片。--runtime 會警告 使用 font_fallback,並且報告會記錄實際繪製的字體。Remotion 需要 @fontsource/*(模板的選擇)或 @remotion/fonts 來使用本地檔案。
  • 這是簡報指定的轉場嗎? feel.transition 應出現在每個 剪接點周圍的影格中,而不是淡出到黑色。

完成條件 你已經閱讀了節拍影格和每個接縫條,回答了上述 每個問題,並且「發布檢查清單」下的每一行都成立。

5. 渲染

node scripts/motion-render.mjs --brief ./my-video/brief.json
node scripts/motion-render.mjs --brief ./my-video/brief.json --batch rows.json --no-audio

包裝程式會從簡報中讀取路線、格式、影格率和 slug,並且在簡報、靜態檢查、工具、資源或執行時期檢查要求停止時,在花費任何渲染時間之前停止。失敗時退出碼為 1,未驗證的需求時退出碼為 3。 --no-checks 跳過驗證並在報告中記錄這個情況。然後它會進行 lint、渲染、 使用 ffprobe 測量檔案,並寫入 <out>.report.json。

當 audio.policy 為 generated 時,在任何一種路線下,它都會使用 music.mjs 合成背景音樂,僅渲染影片(不包含音訊),然後透過一個 ffmpeg 指令將兩者混合 — 這樣組合程式碼就永遠不會依賴於引擎的音訊混音器。然後它會測量 該檔案是否具有音訊串流,以及是否不是靜音的。

對於透明背景:使用 --format webm 或 --format mov — H.264 無法承載 Alpha 通道。 --no-audio 跳過背景音樂並提供一個沒有音訊串流的檔案。GIF 無法承載 音訊,因此除非你傳遞 --no-audio,否則對於包含背景音樂的簡報,系統會拒絕輸出 GIF。

使用 --batch 時,一個簡報加上一個行檔案會變成 N 部影片:HyperFrames 原生渲染 行,Remotion 為每一行獲得一個 props 檔案。批次僅限影片,並且對於包含背景音樂的簡報,系統會拒絕,除非你傳遞 --no-audio。

完成條件 檔案存在,報告顯示 rendered,其 notVerified 列表為 空,或者你已告知使用者列表中的內容,並且檔案的第一個和最後一個影格是 刻意設計的。


會無聲失效的合約

HyperFrames — 四件事,全部必須:

  1. 根元素帶有 data-composition-id、data-width、data-height、 data-duration、data-start="0"。
  2. 每個有時序的元素帶有 id + data-start + data-duration。
  3. GSAP 時間軸使用 { paused: true } 建構。
  4. window.__timelines[<data-composition-id>] = tl — 相同的 key。在 補間動畫被添加之後。錯過這個你會得到一個靜止畫面,沒有錯誤。

Remotion — 三件事:

  1. 進入檔案中的 registerRoot(),根元件中的 <Composition>。
  2. interpolate(..., { extrapolateLeft: "clamp", extrapolateRight: "clamp" }) — 每次都要夾緊兩端。
  3. 組合中不能有 Math.random()、Date.now()。請使用 random(seed)。

決定影片看起來是否廉價的四條規則

這些是最常出錯的規則。完整集合及程式碼範例在 references/motion-craft.md。

  1. 只移動動態的部分。 靜止的東西保持不動。閒置的「呼吸」縮放 看起來像機器生成的。
  2. 重疊,不要排隊。 交錯約 15–30% 的元素自身持續時間。 下一件事在前一個還在穩定時就開始。
  3. 文字不要彈跳。 過衝適用於有質量的物體 — 卡片、翻板、 角色。文字、數字和 UI 標籤使用 power3.out / expo.out 並且 永遠不要過衝。
  4. 每個動作只有一個想法。 y + opacity 是「抵達」。加上旋轉和縮放 會讓文字在移動過程中無法閱讀。

此外:轉場應該是退場,而不是淡出後接淡入。那樣 會呈現為一個中間有下沉的跳接。


發布檢查清單

  • brief.json 驗證通過:時序正確、第一影格經過設計、結尾停留 ≥ 2 秒。
  • check-contract.mjs --runtime 顯示 verified,或未驗證的 ID 已 按名稱接受並告知使用者。
  • 文案、數字、使用者名稱和 URL 與撰寫內容一致 — 沒有 lorem ipsum,沒有佔位文字。
  • 時間軸已在組合 ID 下註冊(HyperFrames),或組合已被 npx remotion compositions 列出(Remotion)。
  • Lint/檢查結果乾淨。
  • <out>.report.json 顯示 rendered,並具有預期的尺寸、影格率、長度和音訊。
  • 已檢查影格:每個節拍、每個接縫、手機寬度 — 剪接點無黑色畫面,

…

[為翻譯而截斷]

相關技能