Communitygithub.com

remotion-demo-video

一個精簡的工作流程,用於建構 Remotion 4.x 宣傳/示範/預告影片。

remotion-demo-video 是什麼?

這個技能為開發者提供了一個整合的工作流程,用於在 Remotion 中創建專業的示範影片。其核心洞察是:將影片分解為可獨立渲染的場景,然後在 DaVinci Resolve、Premiere 或 Final Cut Pro 等下游編輯器中組裝,而不是在單一時間軸內處理所有事情。它提供了一個完整的專案腳手架,包含場景範本、動畫原語(useCurrentFrame、interpolate)、以及一個佔位符系統,讓 Claude AI 能先推斷出影片結構,再由使用者補充實際錄製的畫面片段。該技能支援 Remotion Studio 進行即時迭代、具有 alpha 通道的 ProRes 渲染,以及透過 Zod schemas 進行 props 驅動的自訂。它也處理常見的陷阱,例如在生產與開發期間保持預設值同步,以及正確處理 Sequence 元件中的 useCurrentFrame。主要工作流程是:Claude 分析原始材料(論文/規格)、進行腳手架搭建、使用者錄製片段、Claude 交換佔位符、然後進行場景迭代。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add KoeYe/awsome-demovideo-skill

在你喜歡的 AI 中提問

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

說明文件

remotion-demo-video 是做什麼的?

一個精簡的工作流程,用於建構 Remotion 4.x 宣傳/示範/預告影片。它編碼了專案佈局、動畫原語、渲染命令,以及那些需要花費大量時間重新發現的特定陷阱。

何時使用此技能

當使用者想要製作、編輯、渲染或除錯任何 Remotion 影片時觸發。特別適用於:

  • 為產品/論文/儲存庫示引導建立一個新的 Remotion 專案
  • 為現有 Remotion 專案新增一個場景
  • 將預先錄製的螢幕錄影,透過疊加層、標題、轉場,拼接成一部精美的影片
  • 渲染 — 單一場景、完整時間軸、透明(Alpha)疊加層、PNG 序列
  • 除錯 Remotion 特有的奇怪問題(composition-id 不匹配、預設值不同步、在 <Sequence> 內 useCurrentFrame 回傳非預期值、Windows 上 ffmpeg 清理時的 EPERM 錯誤等)

如何看待這個工作流程

一部精美的 Remotion 影片不是「一個你可以渲染成單一 MP4 的巨大時間軸」。它是一組小型的、可獨立渲染的場景——每個場景渲染為自己的片段,然後在下游編輯器(DaVinci Resolve、Premiere、Final Cut)中組裝,在那裡你可以加入音樂、旁白和跨場景轉場。

這是從發布 SimWorld 宣傳片中獲得的最重要洞察,而這個技能應該預設引導使用者採用這個工作流程。試圖在 Remotion 內部完成所有事情——最終時間調整、音訊混音、淡入淡出——既痛苦又緩慢;在編輯器中做這些事情則輕而易舉。

讓每個工具發揮所長

  • Remotion 擅長於: 程式化、可重複、參數化的場景——動畫標題、資料驅動的圖表、UI 模型、任何你原本會在 After Effects 中手動設定關鍵影格的東西。場景邏輯由程式碼驅動;使用同一個標題搭配 30 種不同的產品名稱」只需要修改一個 prop。
  • 下游編輯器擅長於: 時間調整、音訊、淡入淡出、調色、「讓這個場景延長 1.2 秒」。所有這些在編輯器中都是即時可調的,但在 Remotion 中則需要修改程式碼並重新渲染。

工作循環

  1. 決定腳本。 一個拍點式的綱要,每個拍點附上目標秒數。總長度通常為 30–90 秒。
  2. 一次設定好專案外殼。 theme.ts(調色盤、字型、fps、尺寸)、Root.tsx(composition 註冊表)、共享元件(Reveal、ProgressBar、easing 函式)。
  3. 一次建構一個場景。 每個場景都是一個自包含的 <AbsoluteFill> React 元件,以 frame 0 為設計基礎,並有自己的獨立 <Composition>,這樣你就可以單獨渲染它。在 Studio 中迭代(npm run dev)並使用 props 面板;當你滿意時渲染成 MP4(npm run render:<scene>)。
  4. 將每個完成的場景渲染為自己的片段——這是實際的交付成果,而不是完整時間軸的 MP4。每個場景的片段可以直接拖入任何編輯器的時間軸。對於需要透明度的片段(例如,要疊加在螢幕錄影上的下方三分之一處字幕、Logo),請使用 --codec=prores --pixel-format=yuva444p10le --prores-profile=4444。
  5. 選擇性地將場景整合到 Main.tsx 中,使用 theme.ts 中 TIMELINE 常數驅動的 <Sequence> 區塊。這可以讓你進行完整時間軸的預覽渲染(npm run render)來檢查整體流程——但請將其視為預覽,而非主檔。
  6. 在 DaVinci / Premiere / Final Cut 中組裝。 依序將每個場景的片段放入時間軸,調整修剪手柄以獲得精確時間,加入音樂/旁白/音效設計,在場景之間套用轉場(對於這種美學風格,1 幀的淡入淡出通常感覺不錯),調色,然後輸出。

何時建議使用完整的 Remotion 渲染

只有在以下情況,完整的時間軸渲染才是正確的輸出:

  • 使用者沒有下游編輯器且今天就需要一個單一交付成果。
  • 影片完全靜音(完全沒有音樂或旁白)。
  • 沒有比硬剪接更複雜的跨場景轉場(即便如此,使用逐場景的方法在程式碼中調整也更容易)。

否則,預設建議使用逐場景渲染加上編輯器組裝。

此技能附帶一個位於 scaffold/ 的可行腳手架——將其複製作為新專案的起點,然後根據需要閱讀下面的參考資料。

實際的端到端循環(當輸入是一篇論文/規格/儲存庫時)

這是此技能真正設計用來處理的工作流程。使用者通常不會走進來說「我想要一個顯示 X 的動畫標題」。他們帶來的是一篇論文 PDF、一個專案規格或一個現有的儲存庫,問題是「把這個變成一部 60 秒的影片」。這個技能的存在就是為了讓這個循環變得快速且易於處理。

1. 原始資料        →  論文 PDF / 規格 / 現有儲存庫 / README
        ↓
2. Claude 分析    →  提取敘事節奏;找出每個節拍需要
                     展示的內容(UI 畫面、實驗
                     錄影、圖表、代理人 POV 等)
        ↓
3. Claude 搭建腳手架   →  場景程式碼 + 在每個視覺區域中放置
   使用佔位符             <VideoPlaceholder slot="..." />,並建立一個
                         ASSETS.md 列出使用者需要錄製的
                         所有片段(slot 名稱、時長、應顯示的內容)
        ↓
4. 使用者錄製素材  →  將 mp4 放入 public/clips/<slot>.mp4
                     符合腳手架中的 slot 名稱
        ↓
5. Claude 將      →  將 <VideoPlaceholder> 替換為
   佔位符替換為片段    <OffthreadVideo src={staticFile("clips/<slot>.mp4")}>
        ↓
6. 逐場景迭代     →  npm run render:<scene>,觀看,調整文字 /
                     時間/動畫,重新渲染。程式碼端的
                     變更很快;如果需要重新錄製素材,
                     那就是循環中最慢的部分。
        ↓
7. 在編輯器中組裝  →  將逐場景的 MP4 放入 DaVinci / Premiere / FCP,
                     加入音樂 + 旁白 + 跨場景
                     轉場,輸出。

第 2 步詳解 — 分析原始資料

當使用者遞交論文/規格時,在編寫任何程式碼之前執行此操作:

  1. 提取敘事。 3–5 個節點的敘事弧線是什麼?(「問題 → 我們的方法 → 關鍵結果 → 影響」是一個起點模板;根據實際論文進行調整。)敘事驅動場景列表。
  2. 對於每個節點,決定要展示什麼。 僅有動畫文字很無聊。每個節點都應該有一個具體的視覺內容——一個 UI 畫面、一個實驗錄影、一個圖表、一個比較、一個系統圖表。將視覺內容與主張匹配起來:如果論文聲稱「方法 X 快 3 倍」,則展示並排的時間比較。
  3. 區分 Remotion 生成的內容與使用者必須錄製的內容。 Remotion 擅長於:標題、轉場、圖表、UI 模型、佈局、動畫圖表。Remotion 無法生成:使用者產品的真實螢幕錄影、實驗素材、代理人 POV、任何來自專案外部的東西。將這些列為使用者提供的素材。
  4. 在搭建腳手架之前先草擬時間軸。 逐個節點,附上目標時長,總和為 30–90 秒。更新 theme.ts 中的 TIMELINE 以匹配。應在建立場景之前確定總長度,以便每個場景知道其時間預算。

第 3 步詳解 — 使用佔位符搭建腳手架

此技能的關鍵交接慣例:slot 名稱。使用者需要錄製的每個片段都有一個穩定的 slot 字串。佔位符和實際片段共享這個 slot 名稱。

// 在搭建腳手架期間:
<VideoPlaceholder
  slot="agent-loop"
  description="連續代理人錄影:行走、失敗、使用更新後的政策重試。"
  accent={COLORS.blue}
/>

// 在使用者錄製 public/clips/agent-loop.mp4 之後,切換為:
<OffthreadVideo
  src={staticFile("clips/agent-loop.mp4")}
  muted
  style={{ position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" }}
/>

始終在腳手架根目錄中撰寫一個 ASSETS.md(腳手架附帶一個模板)。它列出使用者需要填補的每個 slot,包括:slot 名稱(= 檔名)、應顯示的內容、目標時長、建議的長寬比,以及任何時間標記(例如「失敗事件約在 7 秒標記處」)。這是使用者錄製任務的唯一真理來源。

第 4–5 步詳解 — 素材交接

使用者回傳時會將檔案放入 public/clips/ 中。需要檢查三件事:

  1. 檔名與 slot 名稱完全匹配。 agent-loop.mp4,而不是 agent_loop.mp4 或 AgentLoop.mp4。
  2. 時長至少與場景長度相同(或者如果較短且旨在重複,則使用 <Loop>)。
  3. 長寬比合理 — 對於全幀場景,匹配 composition 的 1920×1080。對於 2×2 網格中的卡片,4:3 或 16:9 都可以;保持一致就好。

然後機械式地將每個 <VideoPlaceholder> 替換為 <OffthreadVideo>。每個 slot 只需更換一行;動畫邏輯無需更改。如果使用者的錄影對時間敏感(例如,「失敗事件在 7 秒處」),則將其作為場景 prop 暴露出來,這樣可以調整時間相關的疊加層(FAIL 戳記、獎勵數字)而無需重新錄製。

為什麼這個循環對這個技能很重要

這個技能的工作不是「按需編寫 Remotion 程式碼」——而是讓從原始資料到成品影片的循環變得易於處理。佔位符模式讓 Claude 能夠一次性搭建整個影片的結構,然後交回一份 ASSETS.md,讓使用者確切知道要錄製什麼。沒有它,循環就會停滯——使用者錄錯了東西,或者搭建腳手架需要等待素材,或者程式碼結構必須在事後進行改造。

當使用者帶著原始資料出現時,正確的開場白通常是:

「讓我先閱讀論文/規格。然後我會提出一個逐場景的綱要,附上目標時長、你需要錄製的片段列表,並使用佔位符搭建程式碼腳手架,這樣你就可以在我繼續建立場景的同時開始錄製。」

新專案的快速入門

# 1. 複製腳手架
cp -r <skill-dir>/scaffold ./my-demo
cd my-demo
npm install

# 2. 開啟 Remotion Studio 進行即時編輯
npm run dev    # 開啟 http://localhost:3000

# 3. 在迭代時渲染單一場景
npm run render:opening

# 4. 準備好時渲染完整時間軸
npm run render

腳手架包含一個可運作的場景(OpeningTitle)、暖奶油色主題、Reveal + easing 函式、一個 ProgressBar、一個佔位用的 Main 時間軸,以及一個已預先配置好渲染腳本的 package.json。

專案佈局(有效的形狀)

my-demo/
├── package.json                      # 渲染腳本、預渲染鉤子
├── remotion.config.ts                # codec / 像素格式預設值
├── tsconfig.json
├── public/
│   ├── assets/                       # 標誌、靜態圖片 (staticFile("assets/..."))
│   └── clips/                        # 螢幕錄影 / 影片來源
├── scripts/
│   └── sync-clips.mjs                # 在每次渲染前正規化片段
└── src/
    ├── index.ts                      # registerRoot(Root)
    ├── Root.tsx                      # <Composition> 註冊表 — id, schema, defaultProps
    ├── theme.ts                      # COLORS, FONT_STACK, RADIUS, SHADOWS, TIMELINE
    ├── fonts.ts                      # @remotion/google-fonts + 本機 @font-face
    ├── Main.tsx                      # 完整時間軸組合器 (<Sequence> 區塊)
    ├── components/
    │   ├── Reveal.tsx                # 淡入 + 上移包裝器 (delay/duration/rise)
    │   ├── Easing.ts                 # EASE_OUT, EASE_IN_OUT (貝茲曲線)
    │   ├── ProgressBar.tsx           # 固定於底部的 4 階段指示器
    │   └── VideoPlaceholder.tsx      # 帶有 slot 標籤的灰色卡片,之後切換為 OffthreadVideo
    └── scenes/
        ├── OpeningTitle.tsx          # 每個檔案一個場景,每個都是一個 <AbsoluteFill>
        ├── ProductReveal.tsx
        ├── AgentLoop.tsx
        └── ...

為什麼是這種形狀:場景是獨立的(易於單獨渲染和迭代),共享的視覺語言存在於 theme.ts + components/ 中,以保持外觀一致,而 Root.tsx 是關於什麼可以渲染的唯一真理來源。

Composition 模式(仔細閱讀)

每個場景導出三樣東西:

  1. 一個 zod schema — 定義 Remotion Studio 中的 props 面板 UI(滑桿、下拉選單)。
  2. 一個 *_DEFAULTS 常數 — 當此場景嵌入完整時間軸時,由 Main.tsx 使用的值。
  3. React 元件本身,類型為 React.FC<Props>。
// src/scenes/ProductReveal.tsx
import { z } from "zod";

export const productRevealSchema = z.object({
  titleSize:     z.number().min(40).max(280),
  subtitleSize:  z.number().min(14).max(80),
  outerPaddingV: z.number().min(0).max(200),
});
export type ProductRevealProps = z.infer<typeof productRevealSchema>;

export const PRODUCT_REVEAL_DEFAULTS: ProductRevealProps = {
  titleSize: 168,
  subtitleSize: 64,
  outerPaddingV: 80,
};

export const ProductReveal: React.FC<ProductRevealProps> = (p) => { ... };

然後在 Root.tsx 中,使用一份內聯的預設值拷貝來註冊它:

<Composition
  id="ProductReveal"
  component={ProductReveal}
  durationInFrames={120}
  fps={30}
  width={1920}
  height={1080}
  schema={productRevealSchema}
  defaultProps={{
    // ⚠ PRODUCT_REVEAL_DEFAULTS 的內聯拷貝 — Remotion Studio 的
    // 「儲存預設 props」會透過 AST 將資料寫回此物件。請保持
    // 與上述導出的常數同步。
    titleSize: 168,
    subtitleSize: 64,
    outerPaddingV: 80,
  }}
/>

為什麼要重複: Remotion Studio 的「儲存預設 props」按鈕會透過 AST 操作來編輯 Root.tsx 中的 defaultProps={…} 字面值。它無法改寫一個匯入的常數。因此,內聯拷貝是 Studio 會修改的那個,而導出的 *_DEFAULTS 則是 Main.tsx 會讀取的那個。當 Studio 寫入新值時,將它們複製到導出的常數中,以便完整時間軸的渲染也能使用它們。這是 references/pitfalls.md 中的陷阱 #4。

動畫原語(你實際需要的小集合)

Remotion 中的所有動畫都是 useCurrentFrame() + interpolate()。沒有內部時鐘,沒有「播放」——每一幀都是 frame 的純函數。

你需要的……

相關技能