/remotion-best-practices
當您撰寫任何 Remotion 合成 — 動畫示範影片、產品逐步教學、黑客松提交作品、有旁白的簡報 — 任何透過 npx remotion render 渲染成 MP4 的內容時,請使用此技能。
此技能整合了兩層知識:
- Remotion 基礎 — 由 Remotion 團隊在
github.com/remotion-dev/skills維護的上游規則檔案(合成、動畫、字型、音訊、轉場、FFmpeg、字幕等)。 - 示範影片工藝規則 — 從建置 vskill / Skill Studio 黑客松示範的長期迭代週期中汲取的經驗教訓。違反這些規則時,會產生「幻燈片」而非可信的產品逐步教學。
在開始創作前,請先閱讀這兩層內容。
範圍與適用性
以下第二層工藝規則源自一個特定專案:vskill / Skill Studio 黑客松示範(Anthropic / Claude Code "Built with Opus" 黑客松,2026 年 4 月)。 它們反映了該產品的外觀與風格 — Studio 風格的面包屑頁首、側邊欄樹狀結構、深色 verified-skill.com 頁面搭配等寬字體、終端機場景、以及「Inter 是 AI 垃圾,獨特襯線字體才是卓越」的論點編輯主題。
請勿將這些規則逐字套用於不相關的示範。 消費型行動應用、財務儀表板、遊戲或 B2B SaaS 簡報,都有其自身的視覺語言、節奏和目標受眾期望。「儲存後發布」流程、
verified-skill.com/queue頁面或包含 PROJECT/PERSONAL/PLUGINS 計數的 Studio 側邊欄,是內容,而非工藝。將此層視為底層技術的參考: 相機縮放模式、游標目標定位紀律、內容貼合高亮矩形、原地狀態轉場、旁白/script.ts 耦合、渲染+音訊增強管線 — 這些是通用的。確切的常數(1.72× 縮放、x=1488 按鈕中心、v1.0.0 → v1.0.1 版本標籤、「Tier-1 patterns · Tier-2 LLM · Socket」屬性)是 Skill Studio 特有的 — 請轉換,而非複製。
第一層 — Remotion 基礎
鏡像上游 remotion-best-practices 技能,位於 https://github.com/remotion-dev/skills/blob/HEAD/skills/remotion/SKILL.md。
新專案設定
當在一個空資料夾或工作區中且沒有現有 Remotion 專案時,請使用以下命令來初始化一個專案:
npx create-video@latest --yes --blank --no-tailwind my-video
啟動預覽
啟動 Remotion Studio 以預覽影片。Studio 的 HMR 會在檔案變更時即時重新載入 — 您不需要單獨的 preview_start 機制,而 Bash 的 run_in_background 是讓它在編輯期間保持活動的正確方式。
npx remotion studio --port=3030
渲染
# 入口點必須是呼叫 registerRoot() 的檔案(通常是 src/remotion/index.ts)
npx remotion render src/remotion/index.ts <CompositionId> out/video.mp4 --concurrency=8 --log=info
常見陷阱:
- 傳遞
Root.tsx作為入口點 → 錯誤:"this file does not contain registerRoot"。請使用index.ts。 TransitionSeries會對直接子元素進行屬性內省;請不要將子元素包裹在<React.Fragment>中。使用flatMap返回一個由<TransitionSeries.Sequence>和<TransitionSeries.Transition>元素組成的扁平陣列。interpolate(frame, [a, b], …)要求a < b嚴格成立。如果您從常數推導出b,請在場景預算設計時對其進行合理性檢查 — Remotion 會在評估的第一個影格就拋出 "inputRange must be strictly monotonically increasing" 錯誤,導致整個合成無法載入。
單影格渲染檢查
npx remotion still <composition-id> --scale=0.25 --frame=30
上游規則檔案涵蓋的主題
(按需從上游技能庫載入 — github.com/remotion-dev/skills/tree/HEAD/skills/remotion/rules/)
compositions.md— 定義合成、靜態圖片、資料夾、預設 props、動態元資料animations.md—interpolate、spring、緩動函數、基於影格的數學transitions.md—@remotion/transitions(淡入淡出、滑動、擦除),如何在TransitionSeries內鏈式使用它們assets.md—staticFile()、Img、Audio、Video、字型載入fonts.md—@remotion/google-fonts和本地字型註冊audio.md— 匯入、裁剪、音量、速度、音調captions.md、subtitles.md— 字幕軌道和同步ffmpeg.md— 透過 FFmpeg 外部命令進行裁剪、串接、音訊操作silence-detection.md、extract-frames.md、get-audio-duration.md、get-video-duration.md— Mediabunny 工具charts.md、gifs.md、light-leaks.md、3d.md— 專門的渲染配方
第二層 — 示範影片工藝規則
這些是經由漫長的迭代週期所獲得的規則。請將它們視為預設值,而非可選的潤飾 — 它們大多來自「這看起來很奇怪,修復它」的回饋,並且經過多輪才解決。
A. 參考忠真度
A1. 始終擷取真實參考
如果使用者說「讓它看起來像這個 YouTube 影片的 2 分 43 秒處」,請提取該影格並仔細研究它。不要憑記憶近似。
SOURCE="/Users/antonabyzov/Movies/.../Source.mov"
DEST_DIR=".specweave/.../assets/keyframes"
for t in 102 105 108 110 112; do
ffmpeg -y -ss "$t" -i "$SOURCE" -frames:v 1 -q:v 2 "$DEST_DIR/at-${t}s.jpg" -loglevel error
done
然後 Read 每張 JPG 圖片,並根據螢幕上實際顯示的內容進行設計 — 字體排版、確切的按鈕標籤、徽章顏色、側邊欄樹狀結構佈局、搜尋輸入框定位、計數值(例如 PROJECT (1)、PERSONAL (0 of 12)、PLUGINS (0 of 50)、AVAILABLE (62))。
A2. 使用真實標誌和圖示,而非近似品
- 鈴鐺徽章
skill-studio-logo.png— 複製到每個 Studio 場景中,並以<Img src={staticFile("...")} />方式使用。不要渲染一個✷字形然後稱其為標誌。 - 提供者圖示 — 為 Claude、Anthropic、OpenAI、OpenRouter、Ollama、LM Studio 取得真實的 SVG/PNG(例如從
lobehub/static-png)。不要用表情符號代替。 - 吉祥物 — 使用 styled div 精確繪製其形狀。Claude Code 吉祥物是一個桃色 (
#e08160) 的身體,有兩個方形眼睛,身體中段的兩側各有一個手部節點,以及兩對腿在底部 (▪ ▪ ▪ ▪)。不要使用 ASCII 藝術。 - 應用程式視窗 Chrome — 當在「Chrome 瀏覽器」中顯示一個網站時,請渲染一個真實的 Chrome 瀏覽器框架:圓角、紅綠燈圓點、‹ › ↻ 導航按鈕、帶鎖的 URL 列,並顯示真實 URL(
localhost:3000/hero,無多餘空格,無中間點)。
A3. 像素級匹配 YouTube 參考佈局
在憑空重新設計場景之前,列出參考影格中的可見元素,並將每個元素與您的輸出進行核對:
- 橫幅文字 — 確切措辭(
Submit skills for verification,而非Submit a Skill) - 索引標籤順序 —
Overview · Edit · Tests · Run · Trigger · Versions - 信任徽章 —
T1 UNSCANNED、Security-Scanned —、Trusted Publisher - 篩選輸入框 — 始終在側邊欄的
AVAILABLE上方 - 計數 — 在各投影片間保持一致(到處都是
PERSONAL (0 of 12),而不是在一張投影片上用(11),另一張用(0 of 12)) - 頁首右側控制項(依此順序):
🔍 Find skills [⌘K]·+ New Skill·● Model selector·🔔 bell
B. 相機縮放
B1. 相機縮放是整個畫布,而非區塊縮放
請不要在 Chrome 框架內縮放單一面板。請將整個 Chrome(頂部欄位 + 主體) 包裹在一個 transform div 中,並對其進行縮放和平移:
<div
style={{
width: "100%",
height: "100%",
transform: `translate(${cameraTx}px, ${cameraTy}px) scale(${cameraScale})`,
transformOrigin: "50% 50%",
willChange: "transform",
}}
>
{/* TOP BAR + BODY */}
</div>
游標 + 點擊波紋 SVG 應放在此包裹器內部,以便它們隨 Chrome 一起縮放並保持黏附在目標上。
B2. 先點擊,再縮放
觀看者需要先在上下文中看到點擊目標,然後被帶入查看結果。順序:
farme 130 游標接近按鈕
farme 174 點擊波紋
farme 184 按鈕顯示「Running…」
farme 188 相機縮放開始(1.0 → 1.55+ 約 30 影格)
farme 220+ 縮放保持 — 在此進行級聯傳遞 / 結果 / 向上滾動顯示
先縮放再點擊感覺像是一張簡報投影片。先點擊再縮放感覺像是使用者執行了操作,而相機跟隨了這個動作。
B3. 選擇一個能實際將 Chrome 推出畫布的縮放比例
適度的 1.1 倍幾乎不會帶來任何變化。要使「頂部欄位離開畫布頂端」,您需要 ≥ 1.5 倍,並結合一個能將焦點帶到畫布中心的平移值。計算目標值 ≥ (canvasHalfHeight) / (焦點到頂部欄位的距離) — 對於一個位於 y=540 且頂部欄位高 64 px 的行,這需要 ≥ ~1.5 倍。預設使用 1.55–1.85 倍 作為「填滿視窗」的設定值。
C. 游標點擊目標
C1. 命中實際元素
當游標落在錯誤的按鈕上時(例如應點 + New Skill 卻點到模型選擇器藥丸),觀看者會認為示範有問題。請每次都根據佈局重新推導目標 — 不要猜測像素值。
對於一個使用 padding: "0 22px" 的 flex 右對齊控制項條:
// 右邊緣 → 22 填充 → bell (32) → 14 → model (~290) → 14 → New Skill (~120) → 14 → Find skills (~150)
NEW_SKILL_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 60 // = 1488 (按鈕中心)
FIND_PILL_X = 1920 - 22 - 32 - 14 - 290 - 14 - 120 - 14 - 75 // = 1339
一旦有了這個常數,請在游標接近插值和游標離開插值中都使用它,以便點擊波紋精確落在藥丸上,而不是其右側 200 像素處。
C2. 在游標接近時高亮目標
在共享的頁首元件(例如 StudioHeader 上的 findActive、newSkillActive)中添加一個 *Active prop,游標場景會在接近和點擊視窗期間將其打開。該按鈕會獲得:
- 1.08 倍縮放
- 透過
box-shadow: 0 0 0 4px rgba(99,102,241,0.30)實現的柔和靛藍色或紫色光暈 transition: all 0.15s ease
D. 高亮與矩形
D1. 高亮矩形是內容寬度,而非全行
當使用者想在兩行終端機文字周圍畫一個紅色矩形時,請不要包裹父級 flex column — 這會橫跨整行。請使用:
<div
style={{
display: "inline-flex",
flexDirection: "column",
alignSelf: "flex-start",
width: "fit-content",
border: "2px solid #dc2626",
borderRadius: 6,
padding: "10px 16px",
backgroundColor: "transparent",
}}
>
{/* 僅此兩行,不要更多 */}
</div>
任何應在矩形之外的內容(例如,第三行「Generating component…」)必須是一個兄弟元素,而不是子元素。
D2. 註釋:優先使用矩形而非橢圓
圍繞一行文字的手繪風格矩形筆劃,閱讀起來像是「畫布上的螢光筆」,這正是大多數使用者說「高亮這個」時的意思。橢圓形可能感覺裝飾性較強。
<svg viewBox="0 0 1000 100" preserveAspectRatio="none">
<rect
x="6" y="6" width="988" height="88" rx="6" ry="6"
fill="none"
stroke="#ea580c"
strokeWidth="3.6"
strokeDasharray="2160"
strokeDashoffset={2160 * (1 - progress)}
/>
</svg>
D3. 使用橘色 (#ea580c) 表示「這是新功能」,紅色 (#dc2626) 表示「這是錯誤」
同一個示範可以同時包含兩者。請不要混淆。
E. 產品 Chrome 的佈局模式
E1. Studio 頁首是一個共享的單一元件
使用一個 StudioHeader.tsx,採用以下標準佈局,並從每個 Studio 場景中調用它:
- 左側:標誌圖片(40 × 40 PNG)+ 「Skill Studio」字標 + 麵包屑
[Authoring|Available] / [scope] / [folder] / [skill] - 右側:🔍 Find skills
[⌘K]· ✦ + New Skill · ● Model selector · 🔔 Bell
將 breadcrumb、bellBadge、findActive、newSkillActive 作為 props 傳遞。這樣每個場景的頁首都是像素穩定的。
E2. 側邊欄在 AVAILABLE 上方有一個固定的篩選輸入框
每個 Studio 側邊欄 — Browse、Update、AuthorEvals、ConsumeInstall、AuthorEditAndPublish — 都在 AVAILABLE 樹狀結構上方使用相同的 Filter skills… 輸入框。在使用者已經搜尋過的投影片上,預先填入上下文相關的查詢(frontend-design)。
E3. 側邊欄寬度和字體排版
- 寬度:400 px(或在具有深度巢狀樹狀結構的投影片上使用 460 px)
- 外部內距:24–30 px
- 組別標題(
AVAILABLE、AUTHORING):18–19 pt,字母間距 1.6,粗細 700 - 子標題(
SKILLS、.CLAUDE):15–16 pt,字母間距 1.4 - 行文字:17–19 pt
- 版本藥丸:13–14 pt 等寬字體,1 px 邊框,內距 3/10
- 垂直間距:區塊間距 12–14 px,區塊標題上方間距 22–36 px
窄而密的側邊欄感覺像設定面板。寬敞的側邊欄感覺像真實的產品 UI。
F. 原地狀態轉場
F1. 在感覺像是同一個畫面的場景之間,不要向左滑動
如果「點擊 Install → 樹狀結構用新技能更新」應該讀起來像是一次連續的互動:
- 在下一個場景上設定
transitionType: null或 將兩個場景合併為一個 - 保持場景之間的 Chrome 完全一致
- 對變化的元素進行動畫處理(計數翻轉、chevron 旋轉、行滑入) — 不要進行全淡入淡出
F2. 強烈高亮新項目
桃色背景 + 2 px 實心橘色邊框 + 陰影 + ✓ Just installed 標註藥丸,是「這是剛剛出現的」的正確強度。微妙的背景色調看起來像預設狀態,觀看者不會注意到。
backgroundColor: "#fff5ee",
boxShadow: `0 0 0 2px ${ORANGE}, 0 8px 22px rgba(234,88,12,0.22)`,
F3. 計數翻轉:脈衝光暈 + chevron 旋轉
當計數改變時(PROJECT (0) → (1)):
- 旋轉 chevron
▸ → ▼(200 ms 過渡) - 在計數後面渲染一個短暫的橘色光暈:在 18 個影格內,透明度
0.45 → 0,縮放0.4 → 2.2 - 在 24 個影格內,從
translateY: -12 → 0滑入新的子行
G. 編輯器 / SKILL.md 編輯模式
G1. 取代必要欄位,切勿移除
一個技能必須始終有一個 description。要升級描述:用紅色刪除線標記原始行,將新描述滑入