這是撰寫 Remotion React 標記語言的指引。 如果此內容不相關,請改為載入 Remotion 最佳實踐。
保留使用者的變更
使用者可能會在對話之外對程式碼進行編輯。
如果您在此期間偵測到意外的變更,請不要覆寫它,假設它是刻意的,或要求確認。
一般規則
在組合或場景元件內部,從 useVideoConfig() 取得 fps,用於所有秒數轉幀數的計算,包括時間屬性如 from、trimBefore、durationInFrames 和 premountFor。將表達式保留在 JSX 節點上(例如 trimBefore={4 * fps}),可讓 Studio 編輯時間,並在組合幀率變更時保持正確。
使用 useCurrentFrame() 和 interpolate() 來驅動動畫。
CSS transition 或 animation 無法正確渲染,需要重構。
Tailwind 動畫類別無法正確渲染,需要重構。
使用 Easing.bezier() 和 Easing.spring() 來自訂時間曲線。
根據 Remotion 互動性最佳實踐來組織您的標記。
對於具有可編輯屬性的場景,偏好使用 Interactive.withSchema({wrapInSequence: true, layout: 'absolute-fill'})。它們的內部標記可以返回一個 fragment;包裝器負責處理佈局和實例樣式。像下方第三條這類有尺寸的元素可以保留預設佈局,並將 style 轉發給它們自己的根元素。將可重複使用的場景註冊為已連線組合。
直接將時間設定在支援它的元件上;避免多餘的 <Sequence> 包裝。
為每個支援 premountFor 的計時元件提供一秒的預掛載:premountFor={fps},其中 fps 來自 useVideoConfig()。將此應用於媒體、互動元件、<Sequence>、<TransitionSeries.Sequence> 和 <TransitionSeries.Overlay>,包括嵌套在場景內的計時元件。當嵌套項目需要在父項目開始之前掛載時,也要預掛載父時間軸項目。不支援 premountFor 的元件(例如 <TransitionSeries.Transition>)則不需要替代方案。
Studio 會編輯建立項目的 JSX 原始節點。將每個組合註冊、片段、場景、圖層和序列都作為獨立的 JSX 節點撰寫,並將其可編輯屬性內聯。程式化迴圈適用於生成的實例被刻意控制為單一來源模板的情況,而非使用者需要分別編輯實例的情況。
import { useCurrentFrame, useVideoConfig, Easing, interpolate, Interactive } from "remotion";
export const FadeIn = () => {
const frame = useCurrentFrame();
const {fps} = useVideoConfig();
return (
<Interactive.Div
name="Title"
premountFor={fps}
style={{
opacity: interpolate(frame, [0, 2 * fps], [0, 1], {
extrapolateRight: "clamp",
extrapolateLeft: "clamp",
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
}}
>
Hello World!
</Interactive.Div>
);
};
將 interpolate() 呼叫保留在 style 屬性中內聯。
使用 scale、translate、rotate 等 CSS 屬性代替 transform。
// 👍 內聯的可編輯關鍵影格和 transform 簡寫
style={{
scale: interpolate(frame, [0, 100], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
output: 'perceptual-scale' // 對於 `scale` 動畫,使用 "output: 'perceptual-scale'"
}),
translate: interpolate(frame, [0, 100], ["0px 0px", "100px 100px"], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
}),
rotate: interpolate(frame, [0, 100], ["20deg", "90deg"], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
easing: Easing.spring({damping: 200}),
}),
}}
// 👎 非內聯數值和 transform 字串在 Studio 中較難編輯
const scale = interpolate(frame, [0, 100], [0, 1]);
style={{
transform: `scale(${scale})`,
}}
資產
將資產放置在專案根目錄的 public/ 資料夾中。
使用 staticFile() 來引用 public/ 資料夾中的檔案。
媒體元件
使用 @remotion/media 中的 <Video> 和 <Audio> 來新增影片和音訊。
使用 <CanvasImage> 元件來新增圖片。
使用 <AnimatedImage> 來新增動畫 GIF、APNG、WebP 或 AVIF 圖片,如果不是使用 Chrome,則使用 @remotion/gif。
使用 staticFile() 處理 public/ 中的檔案,或直接傳遞遠端 URL:
import { Audio, Video } from "@remotion/media";
import { staticFile, CanvasImage, AnimatedImage, useVideoConfig } from "remotion";
export const MyComposition = () => {
const {fps} = useVideoConfig();
return (
<>
<Video src={staticFile("video.mp4")} premountFor={fps} style={{ opacity: 0.5 }} />
<Audio src={staticFile("audio.mp3")} premountFor={fps} />
<CanvasImage
src={staticFile("logo.png")}
premountFor={fps}
style={{ width: 100, height: 100 }}
/>
<Video src="https://remotion.media/video.mp4" premountFor={fps} />
<AnimatedImage src={staticFile('nyancat.gif')} premountFor={fps} />
</>
);
};
如果組合主要是影片或音訊片段的時間軸,請在選擇其來源結構之前先閱讀 video-editing.md。
範例場景
一個帶有下方第三條的背景影片。
下方第三條是一個具有自己時間軸的互動元件,註冊為一個已連線組合。
其文字透過 children 傳遞,accentColor 則是一個可編輯屬性。
淡入效果在呼叫點內聯關鍵影格。
// MyScene.tsx
import { Video } from "@remotion/media";
import { Easing, interpolate, useCurrentFrame, useVideoConfig } from "remotion";
import { LowerThird } from "./LowerThird";
export const MyScene = () => {
const { fps } = useVideoConfig();
const frame = useCurrentFrame();
return (
<>
<Video
name="Background"
src="https://remotion.media/video.mp4"
premountFor={fps}
objectFit="cover"
style={{
position: "absolute",
width: "100%",
height: "100%",
}}
/>
<LowerThird
name="Lower third"
from={1 * fps}
premountFor={fps}
accentColor="#0b84f3"
style={{
opacity: interpolate(frame, [1 * fps, 2 * fps], [0, 1], {
extrapolateRight: "clamp",
extrapolateLeft: "clamp",
easing: Easing.bezier(0.16, 1, 0.3, 1),
}),
}}
>
Jane Doe, Product Designer
</LowerThird>
</>
);
};
// LowerThird.tsx
import type React from "react";
import { Interactive, type InteractivitySchema } from "remotion";
type LowerThirdProps = {
readonly children: React.ReactNode;
readonly accentColor: string;
readonly style?: React.CSSProperties;
};
const LowerThirdInner: React.FC<LowerThirdProps> = ({
children,
accentColor,
style,
}) => {
return (
<Interactive.Div
style={{
position: "absolute",
left: 80,
bottom: 80,
display: "flex",
alignItems: "center",
gap: 20,
backgroundColor: "white",
borderRadius: 16,
padding: "20px 32px",
color: "black",
fontFamily: "Helvetica, Arial, sans-serif",
fontSize: 48,
fontWeight: 600,
...style,
}}
>
<div
style={{
width: 8,
alignSelf: "stretch",
borderRadius: 4,
backgroundColor: accentColor,
}}
/>
{children}
</Interactive.Div>
);
};
const lowerThirdSchema = {
...Interactive.childrenSchema,
accentColor: {
type: "color",
default: "#0b84f3",
description: "Accent color",
},
} as const satisfies InteractivitySchema;
export const LowerThird = Interactive.withSchema({
Component: LowerThirdInner,
componentName: "LowerThird",
schema: lowerThirdSchema,
wrapInSequence: true,
});
import { Composition } from "remotion";
import { LowerThird } from "./LowerThird";
import { MyScene } from "./MyScene";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="MyScene"
component={MyScene}
durationInFrames={60}
fps={30}
width={1280}
height={720}
/>
<Composition
id="LowerThird"
component={LowerThird}
durationInFrames={30}
fps={30}
width={1280}
height={720}
defaultProps={{
children: "Jane Doe, Product Designer",
accentColor: "#0b84f3",
}}
/>
</>
);
};
延遲與裁剪
直接將時間屬性放在支援它的元件上。有關支援的屬性、範例和操作順序,請參閱時間屬性。
地圖
如果要在影片中包含地圖,請參閱 Remotion 地圖。
文字高亮與註解
如需文字高亮(高亮標記)、圓圈、底線、刪除線、劃掉文字、方塊,請參閱 text-highlights.md。
多場景影片
如果計劃製作包含多個連續場景的影片,請參閱 multi-scene-video.md。
已連線組合
當一個場景或圖層群組需要自己的可編輯時間軸時,請遵循 connected-compositions.md。對於多場景影片中的重要場景,較偏好使用此結構。
預先組合動作
對於像 Pre-compose Ambient glow (src/BarChart.tsx:134) 這樣的 Studio 請求,請在給定位置找到選擇的序列標記。建立一個已連線組合,遵循 connected-compositions.md:將標記提取到一個命名元件中,最好使其成為互動元件(使用 Interactive.withSchema({wrapInSequence: true})),並在根目錄中使用唯一的 <Composition> 註冊相同的匯出元件參考。直接使用其時間屬性渲染互動元件,或當包裝器有特定用途時,將其作為序列的唯一子元素渲染。如果選擇的節點已經是一個序列,請保留其屬性並提取其子元素。元件提取若沒有註冊組合,則無法完成預先組合請求。
將繼承的樣式(例如 fontFamily)和字型載入提取到提取出的元件中;請參閱獨立於父元素。
旁白
如需使用 ElevenLabs TTS 為 Remotion 組合添加 AI 生成的旁白,請參閱 voiceover.md。
嵌入影片
如需關於嵌入影片的進階知識(裁剪、音量、速度、循環、音調),請參閱 embedding-videos.md。
嵌入音訊
如需進階音訊功能(如裁剪、音量、速度、音調),請參閱 audio.md。
裁剪
如果需要裁剪元件的可見矩形,請參閱 cropping.md。
轉場
如需場景轉場模式,請參閱 transitions.md。
動態模糊
當添加動態模糊或運動軌跡時,請閱讀 motion-blur.md 以了解首選的 HTML-in-canvas 方法、預覽需求和替代方案。
視覺與像素效果
當添加視覺效果時,首先確定它應該影響的元素或群組。
如果目標元件支援 effects 且以下內建效果符合需求,請優先使用該效果而非 CSS 近似效果。例如,當暈影效果應只影響特定影片時,直接將 vignette() 應用於 <Video> 的 effects 屬性。
這些元件直接接受 effects:
| Import from | Components |
|---|---|
remotion | <Img>, <CanvasImage>, <AnimatedImage>, <Solid>, <HtmlInCanvas> |
@remotion/media | <Video> |
@remotion/gif | <Gif> |
@remotion/rive | <RemotionRiveCanvas> |
@remotion/shapes | <Arrow>, <Callout>, <Circle>, <Ellipse>, <Heart>, <Pie>, <Polygon>, <Rect>, <Spark>, <Star>, <Triangle> |
普通的 HTML 元素、<Interactive.*> DOM 包裝器、<AbsoluteFill> 和 <Sequence> 不直接接受 effects。若要對其內容套用效果,請將它們包裹在 <HtmlInCanvas> 中,並將 effects 屬性放在包裝器上。
對於其他元素,在合適的情況下,優先使用常規的 HTML 和 CSS。當需要對整個群組進行後處理且環境支援時,考慮將一個群組包裹在 <HtmlInCanvas> 中。
在套用效果之前,請先閱讀 effects.md 以了解導入方式、參數和設定。它還涵蓋了當沒有內建效果匹配時,使用 createEffect() 建立可重複使用的自訂效果。
可用效果
來自 @remotion/effects 的內建效果:
- 顏色與色調:
brightness(),colorCorrection(),colorKey(),contrast(),duotone(),exposure(),grayscale(),hue(),invert(),levels(),linearGradient(),linearGradientTint(),lut(),saturation(),shadowsHighlights(),thermalVision(),tint(),vibrance(),whiteBalance(). - 模糊與軌跡:
blur(),lightTrail(),linearProgressiveBlur(),radialProgressiveBlur(),regionBlur(). - 失真、扭曲與疊加:
bubbles(),chromaticAberration(),cloudOverlay(),colorOverlay(),displacement(),glitch(),imageOverlay(),jigsaw(),mirror(),noise(),noiseOverlay(),overlay(),pixelate(),pixelateRegion(),scanlines(),shake(),snow(),storm(),vignette(). - 3D與幾何:
perspective(),pinch(),pinwheel(),polaroid(),ripple(),swirl(),tunnel(),wave(). - 文字與圖案:
title(),pattern().
對於不支援 effects 的元件,例如當您需要對 <Interactive.Div> 的內容應用效果時,首先將內容包裹在 <HtmlInCanvas> 中。
import { HtmlInCanvas } from "remotion";
import { blur, vignette } from "@remotion/effects";
<HtmlInCanvas effects={[blur(5), vignette({spread: 0.1, opacity: 0.5})]}>
<Interactive.Div>
<div>我的內容</div>
</Interactive.Div>
</HtmlInCanvas>
圖表
如需長條圖、圓餅圖和氣泡圖,請參閱 charts.md。