remotion-best-practices (remotion-dev/skills)
將 Remotion 工作導向對應指南:影片建立、標記、地圖、多媒體與互動。
Remotion 技能:影片品質與未使用技能時相同,也與只把規則寫成一句話時相同,但 Token 用量是未使用技能的 1.4 倍。
Codex CLI · gpt-6-astra
22.9 / 30
相對未使用技能的提升:-0.01 · 視情況推薦 · 18 次執行
視情況推薦:提升幅度 -0.01 低於 +1.0。推薦條件為總分至少 22/30、產出品質至少 3.5、提升幅度至少 +1.0。
SOTA
透過使用 Codex 測試。
涵蓋 Codex, Claude Code
Codex CLI 0.166(SOTA 等級):18 次評分執行。依我們的等級規則,在這裡通過也涵蓋 Claude Code;但這不代表第二等級的結果。
分數
每個維度為 0 到 5 分,六個維度相加即為滿分 30 的總分。每個維度都是 5 分最好。成本 5 分代表便宜又快速;安裝 5 分代表容易安裝。
- 觸發可靠性
- 5.0
- 相對未使用技能的提升
- 2.0
- 產出品質
- 4.9
- Token 與時間成本
- 3.0
- 安裝與可攜性
- 4.0
- 安全性
- 4.0
安全審查
安全靜態掃描:13 CRITICAL / 16 HIGH / 0 MEDIUM。人工審查:可在無網路沙箱中安全執行。掃描結果不能證明技能一定安全。
安裝
npx skills@latest add remotion-dev/skills --skill remotion-best-practices
固定 Commit: 30d4553ecd46fbc5212fd0ff006ae43af522158b
測試日期: 2026-11-02
我們測了什麼
- 15 秒產品預告 — 在這個 Remotion 專案中(React 元件位於 src/,composition id 為 'Main',以 npx remotion render src/index.ts Main 渲染),為 Tidepool 打造一支 15 秒、1920x1080、30 fps 的產品預告;Tidepool 是每月寄送的海苔零食訂閱服務。畫面上必須出現的文字:…
- 20 秒動態長條圖解說 — 在這個 Remotion 專案中(React 元件位於 src/,composition id 為 'Main',以 npx remotion render src/index.ts Main 渲染),製作一支 20 秒、1920x1080、30 fps 的動態解說影片:每月營收的長條圖(8 月 $42k、9 月 $58k、10 月 $71k)。標題為「Reven…
- 30 秒直式字幕短片 — 在這個 Remotion 專案中(React 元件位於 src/,composition id 為 'Main',以 npx remotion render src/index.ts Main 渲染),製作一支 30 秒、直式 1080x1920、30 fps 的社群短片,並加上燒錄式字幕。字幕依序如下,每段約在畫面上停留 5 秒…
優點
- 技能即使未被點名也會被採用:6/6 次實驗組執行都讀取了技能檔案。
- 使用技能後的絕對品質很高:4.91 / 5。
缺點
- 相較於未使用技能,沒有可測量的提升(-0.01,落在雜訊範圍內)。
- 一句話提示得分 4.89,使用技能則為 4.91(+0.02)。
- 對照組本來就拿到 4.91:這是天花板效應,因此測試無法顯示提升。
- 每個任務的每個組別 n=2;約 1 分以內的差異屬於雜訊。
評測
在 Mac 測試機上執行 Codex CLI 0.166(gpt-6-astra,低推理),每次執行都使用全新的暫存專案,以及臨時的 HOME/TMPDIR/快取;技能分成已安裝(實驗組)、未安裝(對照組),以及未安裝但把技能的核心要求濃縮成一句話附加在提示詞後(一句話提示組)。每個任務的每個組別各執行 2 次,關閉網路,封鎖 /tmp 寫入。提示詞從未提及技能(下方註明者除外)。環境:所有組別都使用相同的專案範本(composition id 為 Main 的 Remotion 專案)。沙箱沒有網路,也沒有 Remotion 工具,因此各組都無法啟動 Studio 或進行渲染,只能撰寫原始碼。之後我們在另一台離線機器上,以 Remotion 4.0.539 渲染每個專案。技能中「先開啟預覽」的步驟無法執行。
三組對照
| 組別 | 平均分數(0-5) | 每次執行 Token 用量 |
|---|---|---|
| 未使用技能 | 4.91 | 159k |
| 一句話提示 | 4.89 | 156k |
| 使用技能 | 4.91 | 217k |
以 Codex CLI 執行 18 次,採規則式檢查評分,不經 LLM 評審。總分 22.9 / 30,評級為 視情況推薦。
判定:視情況而定(22.9 / 30)。 來源:remotion-dev/skills,skills/remotion-best-practices,固定於提交 30d4553。安裝:npx skills@latest add remotion-dev/skills --skill remotion-best-practices。授權條款: Remotion License(三人以上的公司使用需付費授權;僅限評估)。
這是什麼
remotion-best-practices 技能是 Remotion 官方技能組的路由(remotion-dev/skills,版本 4.0.539,Remotion License)。SKILL.md(約 600 字)會把 agent 導向子技能:建立影片、標記最佳實務(以 useCurrentFrame() 與 interpolate() 驅動動畫、從 useVideoConfig() 取得 fps、不得使用 CSS 轉場或 Tailwind 動畫類別)、地圖、字幕、studio、渲染等。約 12 個 Markdown 子技能、兩個小型本地 .mjs 腳本。它也告訴 agent 開啟 Remotion Studio 預覽,且除非被要求否則不要渲染。
我們如何測試
在 Mac 測試機上使用 Codex CLI 0.166(gpt-6-astra,低推理),每次執行都使用全新的暫存專案與暫存 HOME/TMPDIR/快取,安裝技能(實驗組)、未安裝(對照組),或未安裝但將技能核心要求濃縮成一句話附加在提示詞後(一句話提示組),每個任務每組執行 2 次,網路關閉,/tmp 寫入封鎖。提示詞從未提及技能(以下註明的措辭除外)。
環境:專案範本(composition id 為 Main 的 Remotion 專案)對所有組都相同。沙箱沒有網路也沒有 Remotion 工具,因此各組都無法啟動 Studio 或渲染;它們只寫原始碼。接著我們在另一台離線機器上以 Remotion 4.0.539 渲染每個專案。技能「先開啟預覽」的步驟無法發生。
- 15 秒產品預告片 — 在這個 Remotion 專案中(React 元件在 src/,composition id 為 'Main',以
npx remotion render src/index.ts Main渲染),為 Tidepool 製作一支 15 秒、1920x1080、30 fps 的產品預告片;Tidepool 是每月配送的海藻零食訂閱服務。必須出現在畫面上的文字:the… - 20 秒動態長條圖解說影片 — 在這個 Remotion 專案中(React 元件在 src/,composition id 為 'Main',以
npx remotion render src/index.ts Main渲染),製作一支 20 秒、1920x1080、30 fps 的動態解說影片:每月營收的長條圖(8 月 $42k、9 月 $58k、10 月 $71k)。標題「Reven… - 30 秒直式字幕短片 — 在這個 Remotion 專案中(React 元件在 src/,composition id 為 'Main',以
npx remotion render src/index.ts Main渲染),製作一支 30 秒、直式 1080x1920、30 fps 的社群短片,字幕燒錄在畫面上。字幕依序出現,每句約在畫面上停留 5 秒…
評分方式為程式化檢查(隱藏測試/預埋問題召回/限制條件檢查/視情況進行渲染與 OCR),每次執行 0–5 分。沒有任何 LLM 評審決定分數。
結果
提供給第三組的一句話提示:「用 useCurrentFrame() 與 interpolate()/spring() 驅動每一個動畫(絕不用 CSS transition/animation),從 useVideoConfig() 取得 fps 並用它把秒數換算成影格,並把影片結構化為 composition 內的 <Sequence>/<Series> 場景。」
| 任務 | 對照組分數 | 一句話提示 | 使用技能 | 對照組 Token 數 | 一句話提示 Token 數 | 使用技能 Token 數 | 技能讀取 |
|---|---|---|---|---|---|---|---|
| t1-teaser | 5.0 | 4.93 | 5.0 | 230k | 168k | 254k | 2/2 |
| t2-chart | 4.74 | 4.73 | 4.71 | 121k | 168k | 198k | 2/2 |
| t3-vertical | 5.0 | 5.0 | 5.0 | 124k | 129k | 197k | 2/2 |
平均分數:未使用技能 4.91,使用技能 4.91(差異 -0.01)。每次執行 Token 數:159k 對 217k(1.36 倍);時間 161 秒對 177 秒。一句話提示組:4.89(技能相較一句話提示的增益:+0.02;一句話提示相較無技能的增益:-0.03);一句話提示每次執行 156k Token,因此技能的成本是一句話提示的 1.39 倍。
實際發生了什麼
- 影片品質相同。18 個專案都以正確的尺寸、長度與影格率渲染,OCR 也在每一個專案中找到所有必要文字(名稱、標語、$14 / box、結尾句、圖表標題、字幕)。平均分數:未使用技能 4.91、只有一句話版規則 4.89、使用技能 4.91。所有組別唯一失分的地方,是長條圖解說影片有長時間靜止(15-23% 的影格有動態),以及兩支一句話提示的預告片為 48-52%。
- 我們看了三組預告片的縮圖拼版:全都像完成度很高的產品廣告(奶油色與深綠色場景、包裝袋插畫、價格結尾卡),我們無法替它們排名。
- 技能最主要的具體規則,有沒有它都被遵守。閱讀原始碼:6 個無技能專案中沒有一個呼叫
useVideoConfig()(它們硬編碼 30 fps),6 個技能專案與 6 個一句話提示專案全都用了,且任何組別都沒有專案使用 CSS 轉場或 keyframes。因此那句話承載了同一條規則,而 agent 本來就會在沒有提示的情況下用useCurrentFrame()與interpolate()做動畫。 - 技能每次都被讀取(6/6 次實驗組執行),成本更高:每次執行 217k Token,未使用時 159k(1.36 倍),一句話提示 156k(1.39 倍),14 個指令對 9 個。這是我們測試過的三個影片技能中最低的額外成本。
- 有一部分無法執行。技能的第一道指示是在建置前啟動 Remotion Studio 並開啟預覽;沒有網路也沒有工具,因此沒有發生,所以結果只反映技能的文字。
各面向分數
| 面向 | 分數 | 原因 |
|---|---|---|
| 1_輸出品質 | 4.91 | 使用技能時平均分數 4.91/5(程式化檢查,見各任務 表格)。 |
| 2_相較無技能的提升 | 1.99 | 相較未使用技能的 4.91,-0.01 分(每項任務 n=2;約 1 分以下 屬於雜訊)。 |
| 3_觸發 | 5.0 | 技能檔案在 6/6 次實驗組執行中被讀取。 |
| 4_指令可攜性 | 4 | 路由型技能,含許多子技能檔案;「先開啟 Studio」規則 需要瀏覽器與執行中的開發伺服器,許多 agent 沙箱沒有這些。 |
| 5_效率 | 3 | 1.36 倍 Token(每次執行 217k 對 159k)與 1.10 倍時間(177 秒對 161 秒)。 |
| 6_安全性與衛生 | 4 | Markdown 加上兩個本地 .mjs 腳本(沒有網路、沒有執行);掃描器 命中的是文件範例中的 .env/process.env(Mapbox、 ElevenLabs 金鑰)。Remotion License 對三人以上的公司 需要付費授權。 |
這項測試的限制
- 沙箱中沒有 Studio 預覽、沒有渲染、沒有 Remotion CLI,因此技能的工作流程只被部分演練。
- 三項以程式碼繪製的任務(預告片、長條圖、直式字幕短片);影片素材、音訊、語音產生的字幕、地圖、Lottie、3D 與 SaaS 渲染功能未測試。
- 渲染是在 Linux 上以軟體 GL 進行,動態檢查是很粗糙的影格差異門檻;圖表任務在每組都失分。
useVideoConfig的計數來自閱讀原始碼,不計入 0-30 分。- Remotion License:個人與最多三人的公司免費,超過則需付費;我們僅做評估,並未轉散布。
- 每項任務每組 n = 2:約 1 分以下的差異屬於雜訊。
- 規則式評分只能衡量檢查看得到的部分;無法評判品味,也無法判斷結果是否為最佳可能。
安全性
見 security.md。掃描:CRITICAL 13 / HIGH 16 / MEDIUM 0。判定:可安全執行(網路關閉的沙箱)。乾淨的掃描結果不能證明技能安全。
總結
對於一次性的程式碼繪製影片,技能沒有帶來可測量的差異:agent 本來就能寫出穩妥的 Remotion 程式碼,而一句話的關鍵規則以約 0.7 倍成本重現了它的小幅結構效果。如果你經常建置 Remotion 專案,它便宜到可以一直裝著(子技能涵蓋我們未測試的地圖、字幕與渲染),但這裡沒有證據顯示它能改善簡單的影片。
完整紀錄
執行日誌:remotion-best-practices (Codex CLI, network off, per-run temp HOME/TMPDIR, one row per graded run.) 欄位:任務、組-輪次、得分(0-5)、token、秒、通過的檢查、代理開啟的 skill 檔案。 t1-teaser control-1: 得分 5.0, token 258594, 秒 285.6, 檢查 5/5, 未開啟 t1-teaser control-2: 得分 5.0, token 202623, 秒 189.4, 檢查 5/5, 未開啟 t1-teaser oneliner-1: 得分 4.94, token 218510, 秒 266.6, 檢查 5/5, 未開啟 t1-teaser oneliner-2: 得分 4.92, token 118109, 秒 174.8, 檢查 5/5, 未開啟 t1-teaser treatment-1: 得分 5.0, token 217450, 秒 209.8, 檢查 5/5, 開啟 remotion-best-practices t1-teaser treatment-2: 得分 5.0, token 291582, 秒 227.3, 檢查 5/5, 開啟 remotion-best-practices t2-chart control-1: 得分 4.73, token 130647, 秒 112.9, 檢查 4/5, 未開啟 t2-chart control-2: 得分 4.74, token 112740, 秒 110.9, 檢查 4/5, 未開啟 t2-chart oneliner-1: 得分 4.73, token 140990, 秒 152.9, 檢查 4/5, 未開啟
18 次執行、21 個產出檔案
範例產出
SOTA · 装了 skill:src/Tidepool.tsx(t1-teaser,第 1 次,Codex)
import React from 'react'; import {AbsoluteFill, Sequence, interpolate, Easing, useCurrentFrame, useVideoConfig} from 'remotion'; const cream = '#F6F1DF', ink = '#123E36', lime = '#D9EF79', orange = '#FF8552'; const serif = 'Georgia, "Times New Roman", serif'; const easing = {extrapolateLeft: 'clamp' as const, extrapolateRight: 'clamp' as const, easing: Easing.bezier(.16, 1, .3, 1)}; const Enter: React.FC<{children: React.ReactNode; delay?: number; style?: React.CSSProperties}> = ({children, delay = 0, style}) => { const f = useCurrentFrame(); return <div style={{...style, opacity: interpolate(f, [delay, delay + 18], [0, 1], easing), translate: `0 ${interpolate(f, [delay, delay + 23], [60, 0], easing)}px`}}>{children}</div>; }; const Wave = ({color = ink, bottom = -100}: {color?: string; bottom?: number}) => { const f = useCurrentFrame(); return <svg width="2200" height="300" viewBox="0 0 2200 300" style={{position: 'absolute', left: -100, bottom, translate: `${Math.sin(f / 65) * 65}px 0`}}><path d="M0 95 Q275 -15 550 95 T1100 95 T1650 95 T2200 95 V300 H0Z" fill={color}/><path d="M0 60 Q275 -50 550 60 T1100 60 T1650 60 T2200 60" fill="none" stroke={color} strokeWidth="2"/></svg>; }; const Pouch = () => { const f = useCurrentFrame(); return <div style={{width: 420, height: 610, position: 'relative', rotate: `${-7 + Math.sin(f / 40) * 1.5}deg`, translate: `0 ${Math.sin(f / 28) * 9}px`, filter: 'drop-shadow(18px 25px 0 rgba(18,62,54,.13))'}}> <svg width="420" height="610" viewBox="0 0 420 610" style={{position: 'absolute'}}> <path d="M26 5 H394 L382 55 L407 573 Q411 600 380 604 H40 Q9 600 13 573 L38 55Z" fill={lime} stroke={ink} strokeWidth="3"/> <path d="M29 18 H391 M32 29 H388 M35 43 H385 M22 577 H398 M22 587 H398" stroke={ink} strokeWidth="2" opacity=".35"/> <path d="M22 472 Q120 427 210 477 T399 477 L404 571 H16Z" fill={ink}/> <path d="M25 455 Q120 410 210 460 T397 460" fill="none" stroke={ink} strokeWidth="3"/> </svg> <div style={{position: 'absolute', top: 77, width: '100%', textAlign: 'center', color: ink}}> <div style={{fontSize: 65, fontFamily: serif, letterSpacing: -4}}>Tidepool</div> <div style={{fontSize: 15, letterSpacing: 4, marginTop: 15}}>SEAWEED SNACKS</div> <svg width="190" height="210" viewBox="0 0 190 210" fill="none" style={{marginTop: 18}}><path d="M96 203 C67 143 135 95 96 12 M96 164 C28 163 29 115 45 100 C48 138 85 116 96 164 M99 118 C157 119 163 70 143 59 C143 89 108 79 99 118 M100 71 C57 74 55 36 66 24 C72 49 94 37 100 71" stroke={ink} strokeWidth="9" strokeLinecap="round"/></svg> <div style={{fontSize: 18, letterSpacing: 3, marginTop: 9}}>A LITTLE OCEAN JOY</div> </div> <div style={{position: 'absolute', top: 513, width: '100%', textAlign: 'center', color: cream, fontSize: 20, letterSpacing: 3}}>CRISP • SAVORY • SEAWEED</div> </div>; }; const Chip = ({x, y, angle, index}: {x: number; y: number; angle: number; index: number}) => { const f = useCurrentFrame(); return <svg width="340" height="260" viewBox="0 0 260 200" style={{position: 'absolute', left: x, top: y, rotate: `${angle + Math.sin(f / 35 + index) * 6}deg`, translate: `0 [... excerpt: first 3200 of 8030 characters]