Remotion
建置與維護 Remotion 專案,同時保留使用者的變更。如果檔案意外變更,除非使用者另行確認,否則視為有意為之。
工作流程
- 檢查
package.json、鎖定檔案、現有合成、目前的差異,以及npx remotion versions。重複使用套件管理員和專案結構;將所有remotion/@remotion/*套件保持在完全相同的版本。 - 確認要求的輸出:合成/來源變更、Studio 預覽、渲染媒體、內嵌 Player 或渲染服務。
- 實作確定性、幀驅動的視覺效果,並保持渲染輸入的可序列化性。
- 在 Studio 中預覽。僅在使用者要求媒體檔案時才進行渲染。
- 使用
ffprobe驗證渲染媒體,並檢查代表性幀。 - 回報變更的檔案、預覽/渲染證據以及交付收據。在 Prismer 中,寬鬆的沙箱路徑並非已交付的結果。
Prismer 工件與交付合約
當使用者要求渲染媒體時,將最終檔案寫入 $PRISMER_ARTIFACTS_DIR(dispatch <artifacts_dir>)。將專案骨架、幀、探測檔案和其他中間產物放在 $PRISMER_SCRATCH_DIR 或現有專案樹中。然後將每個要求的最終檔案精確交付一次:
cloud deliver "$PRISMER_ARTIFACTS_DIR/launch-video.mp4"
寫入或渲染檔案並不會附加該檔案。成功的 cloud deliver 收據是交付的唯一權威依據。不要交付預覽幀、暫存音訊或重複編碼,除非使用者要求。如果不存在 dispatch 工件目錄,則將結果保留在使用者核准的專案輸出路徑中,並回報無法交付,而不是自行編造收據。
專案建立與合成
不要在非空專案上進行骨架建立。當沒有合適的專案存在時,請確認 Node.js 和 Git 可用,然後執行:
npx create-video@latest --yes --blank --no-tailwind my-video
cd my-video
npm install
使用有意義的目錄名稱。僅在使用者要求或專案已使用 Tailwind 時才加入 Tailwind。在繼續之前檢查產生的 manifest、config 和全域 CSS:generator 發行版仍可能在要求 --no-tailwind 時發出 Tailwind 相依性和匯入。僅在專案未使用它們時移除這些內容,並保持 Remotion 套件版本一致。
在 Prismer 沙箱映像檔中,對於可能安裝或呼叫遺失套件的每個指令(包括 scaffolding、npm ci、remotion add、探測和渲染),請使用指令範圍的可寫入 npm 快取:
npm_config_cache="${PRISMER_SCRATCH_DIR:-/tmp}/npm-cache" npm ci
不要更改使用者的全域 npm 配置來解決沙箱所有權不符的問題。
保持靜態合成元數據內聯:
<Composition
id="LaunchVideo"
component={LaunchVideo}
durationInFrames={300}
fps={30}
width={1920}
height={1080}
defaultProps={{title: 'Launch day'}}
/>
僅在持續時間、尺寸或屬性真正依賴於輸入、遠端資料或媒體檢查時,才使用 calculateMetadata()。保持 defaultProps 內聯,以便 Studio 可以將屬性編輯儲存回程式碼。對於多場景影片,使用具名 <Sequence> 邊界,並從一個 fps 感知的計劃中推導所有時序。
幀驅動動畫
使用 useCurrentFrame()、interpolate()、spring 或 easing 來驅動渲染動畫。不要使用 CSS 過渡、CSS 動畫、時鐘計時器或 Tailwind 動畫工具;它們不是確定性渲染。
import {
AbsoluteFill,
Easing,
Interactive,
interpolate,
useCurrentFrame,
useVideoConfig,
} from 'remotion';
export const Hero = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
return (
<AbsoluteFill style={{justifyContent: 'center', alignItems: 'center'}}>
<Interactive.Div
name="Hero title"
style={{
opacity: interpolate(frame, [0, fps], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
scale: interpolate(frame, [0, fps], [0.9, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale',
}),
fontSize: 88,
}}
>
Launch day
</Interactive.Div>
</AbsoluteFill>
);
};
優先使用個別的 scale、translate 和 rotate CSS 屬性,而不是組合的 transform 字串。除非刻意需要外推,否則請夾緊有限動畫的兩端。
Studio 可編輯標記
使用 Interactive.* 來處理 HTML 和 SVG 元素,這些元素應在 Studio 中可選取、拖曳、調整大小、旋轉、設定樣式或設定關鍵幀。<Img> 已經是互動式的。
- 為每個互動式元素提供一個簡短、硬編碼、描述性的
name。 - 將一次性文字直接放在元素內部。
- 當 Studio 的寫回功能重要時,將樣式物件、
interpolate()範圍、輸出、easing 和外推保持內聯。 - 僅從
useVideoConfig()解構受支援的值,例如fps、width、height和durationInFrames。 - 避免在可編輯關鍵幀範圍內使用提取的樣式常數、物件展開、計算的效果陣列和任意變數。
對於自訂元件,在實作之前,請查閱官方 Remotion 文件中目前的 make-component-interactive API。
資產、媒體和時序
將本地資產放在 public/ 中,並使用 staticFile() 引用它們:
import {Audio, Video} from '@remotion/media';
import {AnimatedImage, CanvasImage, staticFile} from 'remotion';
export const MediaLayer = () => (
<>
<Video src={staticFile('clip.mp4')} />
<Audio src={staticFile('music.mp3')} />
<CanvasImage src={staticFile('logo.png')} />
<AnimatedImage src={staticFile('sticker.gif')} />
</>
);
當 Chrome 支援的動態影像路徑不適用時,請使用 @remotion/gif。使用 npx remotion add <package> 安裝生態系套件,以保持 Remotion 套件版本一致。
優先使用本地或內容定址的媒體進行可重複的沙箱渲染。不要將 cookies、bearer token、簽署的 URL 或地圖憑證嵌入到來源或合成屬性中。對於非同步資產、字型、字幕和地圖圖塊,將 delayRender() / continueRender() 與失敗時的 cancelRender() 配對使用,以便遺失的相依性明確失敗,而不是等待逾時。
在受支援的元件上使用 from、durationInFrames 和 trimBefore。將不受支援的元件包裝在 <Sequence> 中:
<Sequence name="Product demo" from={2 * fps} durationInFrames={6 * fps}>
<Video src={staticFile('demo.mp4')} trimBefore={1 * fps} />
</Sequence>
將媒體持續時間與預期的可用片段匹配。將場景時序保持在一個計劃中,以便過渡既不會意外重疊,也不會留下空白幀。
對於效果,使用能產生該鏡頭的最簡單技術:
- HTML、SVG 和 CSS。
- 元素上的 Remotion 效果或
HtmlInCanvas包裝器。 - 僅在前兩者無法產生時,才使用自訂效果或著色器。
保持效果陣列穩定。渲染單獨的元素,而不是有條件地更改效果陣列的形狀。
字幕和多媒體檢查
將字幕正規化為 Remotion 的 Caption[] 形狀,並以毫秒為單位保留攝入時間戳記:
import type {Caption} from '@remotion/captions';
const caption: Caption = {
text: 'Hello',
startMs: 0,
endMs: 800,
timestampMs: null,
confidence: null,
};
僅在合成邊界處使用合成 fps 將毫秒轉換為幀。當可用時保留單字時序,將字幕分組為可讀頁面,從幀時鐘進行動畫,並在實際輸出尺寸下驗證換行和安全區域。
使用目前的 @remotion/captions 解析器處理 SRT,而不是撰寫時間戳記解析器。在實作字幕之前,請確認 parse-srt、createTikTokStyleCaptions 和所選轉錄提供者的目前 API。
對於音訊可視化,請使用帶有幀視窗音訊資料的 @remotion/media-utils;永遠不要從即時分析器驅動長條圖或波形。對於圖表和文字動畫,首先計算最終幾何形狀,並使用基於幀的裁切、不透明度或變換來揭示它,以便長條、標籤和字形佈局保持穩定。
使用 Mediabunny 進行瀏覽器端的持續時間、尺寸、修剪、裁切、元資料和容器處理。在使用不熟悉的 API 之前,請閱讀 https://mediabunny.dev/llms.txt。保持 mediabunny 和 @mediabunny/* 版本與專案的 Remotion 版本相容。
地圖
為該鏡頭選擇一種技術:
| 技術 | 使用時機 |
|---|---|
| 準備好的點陣圖 | 確定性的靜態/衛星影像加上動畫覆蓋層就足夠了。 |
| Mapbox | 需要精緻樣式、地球渲染或 3D 建築物。 |
| MapLibre | 偏好無需 Mapbox API 密鑰的開源向量執行時期。 |
| MapTiler | 託管樣式或地理註釋適合專案。 |
| CesiumJS | 需要地形、全球尺度 3D 或飛行攝影機運動。 |
永遠不要提交地圖憑證。確認影像、圖塊和樣式的授權和歸屬。在幀捕捉之前,請等待圖塊、影像、字型和攝影機初始化。從 Remotion 幀時鐘驅動攝影機移動,當可重複性重要時,將地理輸入保持本地或內容定址,並在實際渲染環境中驗證無頭 Chromium/WebGL。
Studio、渲染和驗證
啟動 Studio 而不開啟外部瀏覽器:
npx remotion studio --no-open
使用列印的 URL。直接在 /<composition-id> 開啟合成,例如 http://localhost:3000/LaunchVideo。
有用的 Studio 標誌:
| 參數 | 目的 |
|---|---|
--log=<level> | 設定 error、warn、info 或 verbose。 |
--port=<number> | 請求特定連接埠。 |
--force-new | 為相同的專案和連接埠啟動另一個實例。 |
對於快速的確定性佈局檢查,渲染一個幀:
npx remotion still LaunchVideo out.png --scale=0.25 --frame=30
在 30 fps 下,第 30 幀為一秒。當現有的視覺測試已提供足夠證據時,跳過此步驟。
在渲染之前,驗證 CLI 是否能看到預期的合成:
npx remotion versions
npx remotion compositions
預設讓 Remotion 管理其相容的瀏覽器。Prismer 映像檔也可能攜帶 Playwright 瀏覽器,但其存在並非相容性保證:完整的 Chrome 二進位檔可能在沙箱 crashpad 政策下失敗,而較新的 Headless Shell 可以通過靜止幀渲染,但在多幀渲染中失敗。僅為映像檔擁有的、版本配對的、並已通過相鄰幀渲染測試的可執行檔傳遞 --browser-executable。永遠不要搜尋整個檔案系統來尋找瀏覽器,也不要將成功的啟動視為相容性證據。
僅在使用者要求媒體檔案時才進行渲染:
npx remotion render LaunchVideo out.mp4 --codec=h264
npx remotion still LaunchVideo out.png --frame=0
Prismer 沙箱提供 Node 和 FFmpeg,而 Remotion 在專案快取中管理相容的瀏覽器。除非需要透明或無損輸出,否則優先使用 MP4 中的 H.264 視訊加上 AAC 音訊以獲得廣泛播放。將可寫入的 npm-cache 覆寫範圍限定在每個指令:
npm_config_cache=/tmp/npm-cache npx remotion render LaunchVideo out.mp4 --codec=h264
對於 CJK 內容,明確載入並等待固定的字型;不要僅依賴系統中存在的備用字型家族。檢查相鄰的編碼幀以及隔離的靜止幀:無頭渲染器可能產生正確的靜止幀,而備用字型執行可能在完整渲染期間閃爍或遺失字形。
將媒體檢查視為交付的唯一權威依據:
ffprobe -v error \
-show_entries format=duration:stream=codec_name,width,height \
-of compact out.mp4
確認持續時間、尺寸、編解碼器和預期的音訊串流。檢查代表性幀,包括動畫或文字密集區段中的幾個相鄰幀,或在可能的情況下播放結果。僅成功的渲染命令不是交付證據。如果隔離的靜止幀正確,但編碼的渲染具有部分或閃爍的幀,請使用具有一個捆綁的 serve URL 和一個瀏覽器實例的程式化 renderStill() API 來發出已驗證的幀序列,然後使用沙箱 FFmpeg 組裝它。不要迴圈 CLI 並為每個幀重新捆綁;回報此降級並再次探測組裝的檔案。
Player、編輯器和渲染服務
使用 Remotion 的 <Player> 進行互動式 React 預覽。保持合成可由 Player 和渲染路徑使用;不要分叉視覺邏輯。
根據工作負載選擇渲染架構:
- 瀏覽器/用戶端渲染適用於有邊界、用戶本機的工作。
- Node Worker 和佇列適用於受控伺服器。
- Remotion Lambda 適用於 AWS 原生彈性渲染。
- 當它與託管平台和已安裝的 Remotion 版本匹配時,使用目前的官方 Vercel 或 Cloudflare 整合。
非簡單的渲染應該是非同步的:傳回任務 ID、公開進度和失敗、持久儲存輸出,並使重試具有冪等性。
對於編輯器,明確對合成屬性和時間軸狀態進行建模。保持渲染輸入的可序列化性和版本化,驗證不受信任的屬性,限制遠端資產存取,並將預覽狀態與持久專案狀態分開。
Remotion 的渲染表面是 React。對於 Vue、Angular 或 Svelte 主機,請使用目前的官方整合,並保持 React 合成邊界明確,而不是依賴記憶化的 starter。
目前文件和升級
優先使用目前的官方文件,而不是記憶化的 API。將 .md 附加到 Remotion 文件 URL 以獲取 Markdown,例如:
https://www.remotion.dev/docs/sequence.md
Remotion 文件搜尋可以
…
[為了翻譯而截斷]