Remotion LabRemotion Lab
疑難排解Composition 掛載位置錯誤

Composition 掛載位置錯誤

解決「Composition mounted inside another composition」錯誤,說明 Composition 元件的正確使用位置與場景

錯誤訊息

你可能會看到以下兩種形式的錯誤訊息之一:

在 Remotion Studio 中:

<Composition> mounted inside another composition.

在 Remotion Player 中:

'<Composition> was mounted inside the `component` that was passed to the <Player>.'

問題原因

情境一:在 Remotion Studio 中的巢狀 Composition

這個錯誤發生在你將一個 <Composition> 嵌套在另一個 <Composition> 的組件內部。

// 錯誤:在 MyComp 內部使用 <Composition>
const MyComp: React.FC = () => {
  return (
    <Composition
      id="another-comp"
      width={1080}
      height={1080}
      durationInFrames={30}
      fps={30}
      component={AnotherComp}
    />
  );
};
 
const Index: React.FC = () => {
  return (
    <Composition
      id="my-comp"
      width={1080}
      height={1080}
      durationInFrames={30}
      fps={30}
      component={MyComp}  // MyComp 內部有另一個 <Composition>,這是錯誤的
    />
  );
};

情境二:在 Remotion Player 中使用 Composition

這個錯誤發生在你傳給 <Player> 的組件中,回傳了一個 <Composition> 元素。

// 錯誤:在傳給 Player 的組件中使用 <Composition>
const MyComp: React.FC = () => {
  return (
    <Composition
      durationInFrames={300}
      fps={30}
      width={1080}
      height={1080}
      id="another-component"
      component={AnotherComp}
    />
  );
};
 
const Index: React.FC = () => {
  return (
    <Player
      durationInFrames={300}
      fps={30}
      compositionWidth={1080}
      compositionHeight={1080}
      component={MyComp}  // MyComp 內部有 <Composition>,這是錯誤的
    />
  );
};

根本概念

<Composition> 元件只能registerRoot() 傳入的根組件中使用,用來向 Remotion 登錄可用的合成(composition)清單。

<Composition> 不是一個可以在其他組件中渲染的視覺元件,它僅僅是一個「登錄聲明」。

<Player> 的使用情境中,根本不需要 <Composition> 元件,因為 Player 是直接接受組件的。


解決方案

修正 Remotion Studio 中的巢狀 Composition

移除巢狀的 <Composition>,改為直接掛載組件:

// 正確:直接在 MyComp 中使用 AnotherComp
const MyComp: React.FC = () => {
  return <AnotherComp />;
};
 
// 或者,若需要限制時間或位移,使用 <Sequence>
const MyComp: React.FC = () => {
  return (
    <Sequence from={0} durationInFrames={30}>
      <AnotherComp />
    </Sequence>
  );
};
 
// Root.tsx:在根組件中正確登錄所有 Composition
export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="my-comp"
        width={1080}
        height={1080}
        durationInFrames={90}
        fps={30}
        component={MyComp}
      />
    </>
  );
};

修正 Remotion Player 中的錯誤

直接將目標組件傳給 <Player>,不要透過包裝組件:

import { Player } from "@remotion/player";
import { AnotherComp } from "./AnotherComp";
 
// 正確:直接傳入要播放的組件
const Index: React.FC = () => {
  return (
    <Player
      durationInFrames={300}
      fps={30}
      compositionWidth={1080}
      compositionHeight={1080}
      component={AnotherComp}  // 直接傳入組件,不要傳包含 <Composition> 的組件
    />
  );
};

<Composition> vs <Sequence> 的選擇

很多開發者誤用 <Composition> 是因為想達到 <Sequence> 的效果。以下是選擇指引:

需求正確做法
登錄一個可渲染的合成<Composition>(只能在 Root 組件中)
在特定時間點顯示子組件<Sequence from={30}>
限制子組件的顯示時長<Sequence durationInFrames={60}>
在另一個組件中使用某個組件直接寫 <MyComponent />

正確的專案結構範例

src/
  index.ts          ← 呼叫 registerRoot()
  Root.tsx          ← 只包含 <Composition> 的根組件
  MyComposition.tsx ← 實際的視覺組件(不包含 <Composition>)
  AnotherComp.tsx   ← 另一個視覺組件
// Root.tsx(正確)
import { Composition } from "remotion";
import { MyComposition } from "./MyComposition";
import { AnotherComp } from "./AnotherComp";
 
export const RemotionRoot: React.FC = () => {
  return (
    <>
      <Composition
        id="MyComposition"
        component={MyComposition}
        durationInFrames={150}
        fps={30}
        width={1920}
        height={1080}
      />
      <Composition
        id="AnotherComp"
        component={AnotherComp}
        durationInFrames={90}
        fps={30}
        width={1920}
        height={1080}
      />
    </>
  );
};

延伸閱讀