Remotion LabRemotion Lab
程式碼片段組合多個 Composition

組合多個 Composition

學習如何將多個 Composition 合併成一支完整影片,使用 Series、Sequence 或動態組合技巧。

組合多個 Composition

在製作長影片或多場景影片時,你通常會把不同段落分別開發,最後再組合成一支完整的成品。Remotion 提供了幾種靈活的組合方式。

方法一:使用 <Series> 自動排列

<Series> 是最簡潔的方式,它會自動將子元件按順序排列,不需要手動計算每段的起始幀。

import { Series } from "remotion";
import { Intro } from "./scenes/Intro";
import { MainContent } from "./scenes/MainContent";
import { Outro } from "./scenes/Outro";
 
export const FullVideo: React.FC = () => {
  return (
    <Series>
      <Series.Sequence durationInFrames={90}>
        <Intro />
      </Series.Sequence>
 
      <Series.Sequence durationInFrames={300}>
        <MainContent />
      </Series.Sequence>
 
      <Series.Sequence durationInFrames={60}>
        <Outro />
      </Series.Sequence>
    </Series>
  );
};

然後在 Root 中定義 Composition,總長度就是各段之和:

import { Composition } from "remotion";
import { FullVideo } from "./FullVideo";
 
export const RemotionRoot: React.FC = () => {
  return (
    <Composition
      id="FullVideo"
      component={FullVideo}
      durationInFrames={450} // 90 + 300 + 60
      fps={30}
      width={1920}
      height={1080}
    />
  );
};

方法二:使用 <Sequence> 手動指定位置

當你需要更精確地控制每段的起始時間,或讓多段重疊播放時,使用 <Sequence> 更合適:

import { AbsoluteFill, Sequence } from "remotion";
import { TitleCard } from "./scenes/TitleCard";
import { VideoClip } from "./scenes/VideoClip";
import { LowerThird } from "./scenes/LowerThird";
 
export const FullVideo: React.FC = () => {
  return (
    <AbsoluteFill>
      {/* 標題卡:第 0~60 幀 */}
      <Sequence from={0} durationInFrames={60}>
        <TitleCard />
      </Sequence>
 
      {/* 主要影片片段:第 60~360 幀 */}
      <Sequence from={60} durationInFrames={300}>
        <VideoClip />
      </Sequence>
 
      {/* 下方字幕條:在影片期間,第 90~240 幀疊加顯示 */}
      <Sequence from={90} durationInFrames={150}>
        <LowerThird text="特別來賓:王小明" />
      </Sequence>
    </AbsoluteFill>
  );
};

方法三:從陣列動態生成場景

當場景數量不固定(例如從資料產生影片)時,可以用陣列動態組合:

import { Series } from "remotion";
import { Slide } from "./Slide";
 
interface Scene {
  id: string;
  title: string;
  body: string;
  durationInFrames: number;
}
 
const scenes: Scene[] = [
  { id: "s1", title: "第一章", body: "內容一", durationInFrames: 120 },
  { id: "s2", title: "第二章", body: "內容二", durationInFrames: 150 },
  { id: "s3", title: "第三章", body: "內容三", durationInFrames: 90 },
];
 
export const DynamicVideo: React.FC = () => {
  return (
    <Series>
      {scenes.map((scene) => (
        <Series.Sequence key={scene.id} durationInFrames={scene.durationInFrames}>
          <Slide title={scene.title} body={scene.body} />
        </Series.Sequence>
      ))}
    </Series>
  );
};

動態計算總幀數並傳入 Composition:

const totalFrames = scenes.reduce((sum, s) => sum + s.durationInFrames, 0);
 
export const RemotionRoot: React.FC = () => {
  return (
    <Composition
      id="DynamicVideo"
      component={DynamicVideo}
      durationInFrames={totalFrames}
      fps={30}
      width={1920}
      height={1080}
    />
  );
};

方法四:在 Composition 之間加入轉場

搭配 @remotion/transitions 套件,可以在場景切換時加入淡入淡出、滑動等轉場效果:

import { Series } from "remotion";
import { TransitionSeries, linearTiming } from "@remotion/transitions";
import { fade } from "@remotion/transitions/fade";
import { slide } from "@remotion/transitions/slide";
import { SceneA } from "./SceneA";
import { SceneB } from "./SceneB";
import { SceneC } from "./SceneC";
 
export const VideoWithTransitions: React.FC = () => {
  return (
    <TransitionSeries>
      <TransitionSeries.Sequence durationInFrames={120}>
        <SceneA />
      </TransitionSeries.Sequence>
 
      <TransitionSeries.Transition
        presentation={fade()}
        timing={linearTiming({ durationInFrames: 20 })}
      />
 
      <TransitionSeries.Sequence durationInFrames={150}>
        <SceneB />
      </TransitionSeries.Sequence>
 
      <TransitionSeries.Transition
        presentation={slide({ direction: "from-right" })}
        timing={linearTiming({ durationInFrames: 30 })}
      />
 
      <TransitionSeries.Sequence durationInFrames={90}>
        <SceneC />
      </TransitionSeries.Sequence>
    </TransitionSeries>
  );
};

計算含轉場的總幀數

使用 TransitionSeries 時,轉場期間兩段場景重疊,總幀數需要扣掉轉場長度:

總幀數 = 所有場景幀數之和 - 所有轉場幀數之和
      = (120 + 150 + 90) - (20 + 30)
      = 360 - 50
      = 310 幀

Series vs Sequence 選用建議

情境推薦方式
場景依序不重疊<Series>
場景需要精確定位或重疊<Sequence>
場景由資料動態產生<Series> + map()
場景之間需要轉場效果<TransitionSeries>

延伸閱讀