Communitygithub.com

erencalik/motion-graphics-video-generator-claude

從單一請求生成含音樂的動畫 MP4 動態圖形影片(9:16 Reels 或 16:9)。透過逐幀渲染 HTML/CSS/JS 動畫並以 ffmpeg 合成,適用於動態圖形、動態排版、動態統計數據及 Reels 動畫。

motion-graphics-video-generator-claude 是什麼?

此技能讓 Claude 在程式碼環境中從頭到尾生成 MP4 動態圖形影片,無需任何剪輯軟體或素材庫。它將動畫編寫為單一 HTML 頁面,其中每個元素的位置、大小、顏色與透明度完全由幀數決定(使用 `window.renderFrame(f)`),確保渲染結果確定性。接著透過 Playwright 操控無頭 Chrome 逐幀捕捉畫面(例如 20 秒 × 60 fps = 1200 幀),再使用 ffmpeg 合成為 H.264 編碼的 MP4 影片,並可加入經程式合成、與轉場同步的音樂。支援 9:16(Reels/TikTok/Shorts)與 16:9(YouTube/作品集)兩種格式,長度建議 15–20 秒。用戶可提供品牌素材(商標、照片、顏色、字型)或僅給予風格指令(如動態排版、動畫資訊圖表、粒子效果等)。技能也包含預先測試的 HTML 骨架、Node.js 渲染腳本與 Python 音樂合成腳本,以便產出高品質成果。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erencalik/motion-graphics-video-generator-claude/tree/HEAD

在你喜歡的 AI 中提問

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

說明文件

動態圖形影片

在 Claude 的程式碼環境中從頭到尾產出 MP4 影片,無需剪輯軟體或素材庫。需要啟用程式碼執行與檔案建立(在 claude.ai 上:設定 > 功能)。若為品牌影片,請上傳商標、照片、顏色與字型,或指向品牌風格檔案。以用戶使用的語言回覆。

運作方式

  1. 動畫寫成單一 HTML 頁面。每個元素的位置、大小、顏色與透明度完全根據幀數計算(window.renderFrame(f));不使用 CSS 轉場、setTimeout 或 requestAnimationFrame。這使得渲染結果具有確定性。
  2. 無頭 Chrome(Playwright)捕捉每一幀。20 秒 × 60 fps = 1200 幀。
  3. ffmpeg 將這些幀轉換為 MP4(H.264, yuv420p)。
  4. 音樂以程式碼合成,時間點對齊轉場,並加入影片中。

要求檢查清單(缺少的部分請一次問清楚)

  1. 長度: 15–20 秒為理想。
  2. 格式: Reels/TikTok/Shorts 使用 9:16(1080×1920),YouTube/作品集使用 16:9(1920×1080)。
  3. 素材來源: 網站、上傳的照片、商標,或無素材。
  4. 風格: 說出技術名稱:動態排版、動畫資訊圖表/統計、粒子、網點、地圖/地形、計數器、時間軸。指定技術名稱能獲得更可靠的結果。
  5. 規則與排除: 需搭配的顏色、要省略的內容(例如價格、額外文字)。
  6. 野心: 若用戶說「盡你所能」,Claude 會自行決定概念、調色板與音樂,並更大膽嘗試。

故事 Reel 的現成結構:商標/鉤子開場(0–2 秒)→ 動態排版的故事句子 → 數字在計數器上增長 → 時間軸或地圖 → 結尾卡片(帳號名稱)。請將螢幕上的文字保持在 Reels 安全區域內(上方 210 px、下方 310 px、右方 84 px 淨空)。數字與日期必須有來源;絕對不要動畫化一個虛構的數字。

製作步驟

  1. 以逐秒為單位撰寫場景計畫(表格:時間 | 螢幕顯示內容 | 轉場 | 音效打點)並展示。
  2. 撰寫 scene.html。規則:固定像素尺寸、定義 window.TOTAL(總幀數)和 window.renderFrame(f);使用緩動函式進行插值;字型以 base64 woff2 嵌入(環境可能無法連上 Google Fonts),圖片也以 base64 嵌入。
  3. 先捕捉 3–4 張 PNG 幀並自行檢查(文字溢出、字型錯誤、空白幀)。然後再進行完整渲染。
  4. 用 audio.py 合成音樂;將打點放在場景轉換處。若用戶上傳自己的音樂,則使用該音樂。
  5. 合併,用 ffprobe 驗證長度/解析度,視覺檢查中間幀,交付 MP4。

渲染時間:20 秒、60 fps 約需 8–10 分鐘。快速草稿使用 30 fps,最終版本使用 60 fps。接受以時間碼提出的修改要求(例如「讓 0:07 處的計數器慢一點」)。

模板(已測試;也作為檔案放在此 SKILL.md 旁邊)

scene.html(骨架)

<!doctype html><html><head><meta charset="utf-8"><style>
html,body{margin:0;width:1080px;height:1920px;overflow:hidden;background:#0E0E10;font-family:'Montserrat',Arial,sans-serif}
#s{position:relative;width:1080px;height:1920px}
.t{position:absolute;left:90px;right:90px;color:#F5F1E8;font-weight:800;line-height:1.05}
</style></head><body><div id="s">
<div class="t" id="a" style="top:520px;font-size:120px">5,126</div>
<div class="t" id="b" style="top:680px;font-size:64px;color:#FF5A1F">FAILED PROTOTYPES</div>
</div><script>
const FPS=30,DUR=3;window.TOTAL=FPS*DUR;
const clamp=(x,a=0,b=1)=>Math.min(b,Math.max(a,x));
const easeOut=t=>1-Math.pow(1-t,3);
window.renderFrame=f=>{const t=f/FPS;
 const p=easeOut(clamp(t/0.6));a.style.opacity=p;a.style.transform=`translateY(${(1-p)*80}px)`;
 a.textContent=Math.round(5126*easeOut(clamp(t/1.5))).toLocaleString('en-US');
 const q=easeOut(clamp((t-0.8)/0.5));b.style.opacity=q;b.style.transform=`scale(${0.8+0.2*q})`;};
</script></body></html>

render.js:node render.js scene.html video.mp4 30(若缺少 Playwright:npm i playwright && npx playwright install chromium;若仍失敗,則用 Python Playwright 建立相同的迴圈)

// node render.js scene.html out.mp4 [fps]
const {chromium}=require('playwright');const {spawn}=require('child_process');const path=require('path');
(async()=>{const [,,html,out,fpsArg]=process.argv;const fps=+(fpsArg||30);
const b=await chromium.launch();const p=await b.newPage({viewport:{width:1080,height:1920}});
await p.goto('file://'+path.resolve(html));await p.evaluate(()=>document.fonts.ready);
const total=await p.evaluate(()=>window.TOTAL);
const ff=spawn('ffmpeg',['-y','-f','image2pipe','-framerate',String(fps),'-i','-','-c:v','libx264','-pix_fmt','yuv420p','-crf','18','-preset','medium',out],{stdio:['pipe','inherit','inherit']});
for(let f=0;f<total;f++){await p.evaluate(f=>window.renderFrame(f),f);ff.stdin.write(await p.screenshot({type:'jpeg',quality:92}));}
ff.stdin.end();await new Promise(r=>ff.on('close',r));await b.close();console.log('frames',total);})();

對於 16:9,將 viewport 與頁面尺寸改為 1920×1080。

audio.py:python3 audio.py music.wav <seconds>(numpy 合成:背景音墊 + 打點)

# python3 audio.py music.wav 3   -> 合成的背景音墊 + 打點
import sys,wave,numpy as np
out,dur=sys.argv[1],float(sys.argv[2]);sr=44100;t=np.arange(int(sr*dur))/sr
pad=sum(np.sin(2*np.pi*f*t) for f in (110,164.8,220))*0.08*np.minimum(1,t/0.5)
def hit(at,f0=60):
    x=np.zeros_like(t);m=t>=at;tt=t[m]-at;x[m]=np.sin(2*np.pi*f0*tt*(1+3*np.exp(-tt*30)))*np.exp(-tt*8)*0.6;return x
y=pad+hit(0.0)+hit(0.8,90)
y=y/np.max(np.abs(y))*0.8;fade=np.minimum(1,(dur-t)/0.4);y*=fade
w=wave.open(out,'wb');w.setnchannels(1);w.setsampwidth(2);w.setframerate(sr);w.writeframes((y*32767).astype(np.int16).tobytes());w.close()

合成

ffmpeg -y -i video.mp4 -i music.wav -c:v copy -c:a aac -b:a 192k -shortest final.mp4

限制

  • 可對照片套用特效(粒子、網點、剪裁);無法讓人動起來,也無法做到嘴型同步(請使用專用的虛擬角色/影片模型)。
  • 合成的音樂是電子風格;如需真實樂器或人聲,請上傳音訊檔案。
  • 不得使用用戶不擁有版權的角色或商標。真正的公司商標僅限於新聞/評論情境,並需標註來源。

致謝:基於 Michael Ly 的指南「How to Generate Motion Graphics Videos with Claude」(milleemd.com/guides/motion-graphics-videos)中的方法;此技能的程式碼模板為此技能撰寫。

相關技能