Player 與 Remotion 的程式碼共享
了解如何在 Remotion Player、Remotion Studio 與伺服器端渲染之間共享元件程式碼,以及 Webpack bundle 的注意事項。
Player 與 Remotion 的程式碼共享
使用 Remotion 開發時,你通常會希望讓同一套元件程式碼能夠同時服務於三個場景:
- Remotion Studio — 開發預覽與調整
<Player>元件 — 嵌入 React 應用程式的互動式播放器- 伺服器端渲染(SSR) — 透過 Node.js API 輸出影片檔案
這三個場景雖然目的不同,但核心的 Remotion 元件完全可以共享,不需要重複撰寫。
建議的專案結構
將你的 Remotion 元件集中放置在一個子目錄中,讓應用程式的其他部分和 Remotion 渲染管線都能引用:
src/
├── remotion/
│ ├── index.ts # Remotion 進入點(包含 registerRoot)
│ ├── Root.tsx # 列出所有 Composition
│ └── MyComp.tsx # 實際的影片元件
└── app/
└── App.tsx # 你的 React 應用程式
remotion/MyComp.tsx 中的元件就是可以被三個場景共同使用的程式碼。
在 Player 中使用元件
直接從 remotion/ 目錄匯入元件,傳入 <Player> 的 component prop:
import { Player } from '@remotion/player';
import { MyComp } from './remotion/MyComp';
export const App: React.FC = () => {
return (
<Player
component={MyComp}
durationInFrames={120}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
inputProps={{ title: '我的影片' }}
/>
);
};<Player> 不需要 bundle,它直接使用 React 元件。
在伺服器端渲染中使用元件
SSR 流程則需要先打包(bundle)你的 remotion/index.ts,再進行渲染:
import { bundle } from '@remotion/bundler';
import { renderMedia, selectComposition } from '@remotion/renderer';
import path from 'path';
const bundleUrl = await bundle({
entryPoint: path.resolve('./src/remotion/index.ts'),
});
const composition = await selectComposition({
serveUrl: bundleUrl,
id: 'MyComp',
inputProps: { title: '我的影片' },
});
await renderMedia({
composition,
serveUrl: bundleUrl,
codec: 'h264',
outputLocation: 'out/video.mp4',
inputProps: { title: '我的影片' },
});Bundle 的注意事項
Player 與 SSR 使用不同的 Webpack 設定
<Player> 直接在你的應用程式 Webpack bundle 中執行元件,而 SSR 的 bundle() 則會產生一個獨立的 Webpack bundle。兩者的設定是分開的。
如果你自訂了 Webpack 設定,需要分別在兩處套用:
// remotion.config.ts — 影響 bundle() 與 Remotion Studio
import { Config } from '@remotion/cli/config';
Config.overrideWebpackConfig((currentConfig) => {
return {
...currentConfig,
// 你的自訂設定
};
});// 應用程式的 webpack/vite 設定 — 影響 <Player>
// 例如 next.config.js、vite.config.ts 等避免在 bundle 中呼叫 bundle()
bundle() 是 Node.js API,不可在已打包的瀏覽器端程式碼中呼叫。如果你需要在前端觸發渲染,應透過後端 API 進行,而不是直接在 React 元件裡呼叫 bundle()。
元件必須與 Webpack 相容
因為 SSR 打包會使用 Webpack 處理你的元件,請確認元件中所有使用的語法與套件都能被 Webpack 正確處理。純 React / TypeScript 程式碼通常沒有問題,但需要特別注意:
- 僅限 Node.js 的模組(如
fs、path)不能在元件中直接使用 - 使用動態
import()時需確認 Webpack 支援 - CSS Modules、SVG 等特殊資源格式需要對應的 Webpack loader
共享型別定義
若你的元件接受 Props,建議將 Props 型別定義抽離到獨立檔案,方便 Player 端與渲染端共同引用:
// remotion/types.ts
export type MyCompProps = {
title: string;
subtitle?: string;
durationInFrames: number;
};// remotion/MyComp.tsx
import type { MyCompProps } from './types';
export const MyComp: React.FC<MyCompProps> = ({ title, subtitle }) => {
// ...
};// app/App.tsx
import type { MyCompProps } from './remotion/types';
import { MyComp } from './remotion/MyComp';
import { Player } from '@remotion/player';
const props: MyCompProps = {
title: '共享型別',
durationInFrames: 120,
};
export const App: React.FC = () => (
<Player
component={MyComp}
durationInFrames={props.durationInFrames}
compositionWidth={1920}
compositionHeight={1080}
fps={30}
inputProps={props}
/>
);使用 Zod Schema 驗證 Props
搭配 @remotion/zod-types,你可以讓 Props 驗證在三個場景中保持一致:
import { z } from 'zod';
export const myCompSchema = z.object({
title: z.string(),
subtitle: z.string().optional(),
});
export type MyCompProps = z.infer<typeof myCompSchema>;Remotion Studio 會自動根據 Schema 產生可互動的 Props 編輯面板。詳見 Schema 驗證。