Communitygithub.com

Prismer-AI/PrismerCloud

用於涉及 Remotion 合成、Studio、Player、@remotion 套件、程式化影片渲染、字幕、媒體處理、地圖,或 Remotion 與 Mediabunny 升級的任務。

PrismerCloud 是什麼?

此技能專為建置與維護 Remotion 專案而設計,確保使用者變更得以保留。它定義了完整的工作流程:從檢查 `package.json` 和鎖定檔案,到確定性的幀驅動動畫、Studio 可編輯標記、資產管理,以及最終的媒體交付。技能強調使用 `useCurrentFrame()` 和 `interpolate()` 等 Remotion 原生 API 來實現確定性渲染,避免 CSS 動畫或時鐘計時器。它支援多種渲染目標,包括 Studio 預覽、靜止幀和影片渲染,並強制透過 `cloud deliver` 指令將最終成品交付至 `$PRISMER_ARTIFACTS_DIR`。技能還涵蓋字幕處理、地圖整合(Mapbox、MapLibre、CesiumJS)、音訊可視化,以及 Player 和 Lambda 等進階渲染服務。對於升級,它建議參考官方文件,並使用 `npx remotion add` 來安裝生態系套件,以保持版本一致性。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Prismer-AI/PrismerCloud/tree/HEAD/sdk/cloud/catalog/skills/remotion

在你喜歡的 AI 中提問

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

說明文件

Remotion

建置與維護 Remotion 專案,同時保留使用者的變更。如果檔案意外變更,除非使用者另行確認,否則視為有意為之。

工作流程

  1. 檢查 package.json、鎖定檔案、現有合成、目前的差異,以及 npx remotion versions。重複使用套件管理員和專案結構;將所有 remotion / @remotion/* 套件保持在完全相同的版本。
  2. 確認要求的輸出:合成/來源變更、Studio 預覽、渲染媒體、內嵌 Player 或渲染服務。
  3. 實作確定性、幀驅動的視覺效果,並保持渲染輸入的可序列化性。
  4. 在 Studio 中預覽。僅在使用者要求媒體檔案時才進行渲染。
  5. 使用 ffprobe 驗證渲染媒體,並檢查代表性幀。
  6. 回報變更的檔案、預覽/渲染證據以及交付收據。在 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>

將媒體持續時間與預期的可用片段匹配。將場景時序保持在一個計劃中,以便過渡既不會意外重疊,也不會留下空白幀。

對於效果,使用能產生該鏡頭的最簡單技術:

  1. HTML、SVG 和 CSS。
  2. 元素上的 Remotion 效果或 HtmlInCanvas 包裝器。
  3. 僅在前兩者無法產生時,才使用自訂效果或著色器。

保持效果陣列穩定。渲染單獨的元素,而不是有條件地更改效果陣列的形狀。

字幕和多媒體檢查

將字幕正規化為 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 文件搜尋可以

…

[為了翻譯而截斷]

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相關技能