Remotion LabRemotion Lab
疑難排解defaultProps 過大錯誤

defaultProps 過大錯誤

說明 Remotion 渲染時出現 defaultProps too big 序列化錯誤的原因,以及如何透過精簡預設屬性來解決此問題

defaultProps 過大錯誤

錯誤訊息

渲染時若遇到以下錯誤:

defaultProps too big - could not serialize - the defaultProps of composition
with ID "[composition-id]" - the object that was passed to defaultProps was
too big. Learn how to mitigate this error by visiting
https://remotion.dev/docs/troubleshooting/serialize-defaultprops

或另一種變體:

defaultProps too big - Could not serialize - an object that was passed to
defaultProps was too big. Learn how to mitigate this error by visiting
https://remotion.dev/docs/troubleshooting/serialize-defaultprops

第二種變體表示 defaultProps 本身可能並不太大,但整個合成清單作為一個整體對序列化來說過大。

為什麼會發生此錯誤

Remotion 嘗試使用 getCompositions() 取得合成清單,並將其從無頭瀏覽器複製到 Node.js。在此操作過程中,JavaScript 物件需要轉換為字串。

此操作的上限為 256MB,但根據 Remotion 執行的機器,錯誤也可能在更小的資料量時發生。

如何修復

核心原則:避免在 defaultProps 中傳遞大型資料

不要將大型資料傳遞給 defaultProps,而是在元件內部基於精簡的 defaultProps 衍生大型資料。

範例比較

錯誤做法:將大型音訊資料作為 defaultProps

// ❌ 避免 — 大型資料塊作為 defaultProps
import { getAudioData } from "@remotion/media-utils";
import { useEffect, useState } from "react";
import { cancelRender, Composition, continueRender, delayRender, staticFile } from "remotion";
 
const MyComp: React.FC<{ audioData: AudioData | null }> = ({ audioData }) => {
  return null;
};
 
const RemotionRoot = () => {
  const [audioData, setAudioData] = useState<AudioData | null>(null);
  const [handle] = useState(() => delayRender());
 
  useEffect(() => {
    getAudioData(staticFile("audio.mp3"))
      .then((data) => {
        setAudioData(data);
        continueRender(handle);
      })
      .catch((err) => {
        cancelRender(err);
      });
  }, [handle]);
 
  return (
    <Composition
      id="MyComp"
      component={MyComp}
      defaultProps={{
        audioData, // ❌ 傳遞了完整的音訊資料物件
      }}
    />
  );
};

正確做法:只傳遞 URL,在元件內部取得資料

// ✅ 正確 — 只傳遞 URL 作為 defaultProps
import { getAudioData } from "@remotion/media-utils";
import { useEffect, useState } from "react";
import { cancelRender, continueRender, delayRender, staticFile } from "remotion";
 
const MyComp: React.FC<{ audioSrc: string }> = ({ audioSrc }) => {
  const [audioData, setAudioData] = useState<AudioData | null>(null);
  const [handle] = useState(() => delayRender("載入音訊資料"));
 
  useEffect(() => {
    getAudioData(audioSrc)
      .then((data) => {
        setAudioData(data);
        continueRender(handle);
      })
      .catch((err) => {
        cancelRender(err);
      });
  }, [audioSrc, handle]);
 
  return null;
};
 
const RemotionRoot = () => {
  return (
    <Composition
      id="MyComp"
      component={MyComp}
      defaultProps={{
        audioSrc: staticFile("audio.mp3"), // ✅ 只傳遞 URL 字串
      }}
    />
  );
};

其他常見的錯誤模式

錯誤:傳遞 Data URL 或 Buffer

// ❌ 避免
defaultProps={{
  imageData: "data:image/png;base64,iVBORw0KGgo...", // 非常大的 Base64 字串
}}
 
// ✅ 正確
defaultProps={{
  imageSrc: "https://example.com/image.png", // 傳遞 URL
}}

錯誤:傳遞大型 JSON 資料集

// ❌ 避免
defaultProps={{
  chartData: hugeArrayOf10000Items, // 大型資料陣列
}}
 
// ✅ 正確
defaultProps={{
  dataUrl: "/api/chart-data", // 在元件內部取得資料
}}

邊界情況:整個合成清單過大

如果您有非常多的合成(數百個),即使每個 defaultProps 都很小,組合起來也可能超過限制。解決方案:

  • 減少合成數量,使用參數化方式動態生成
  • 將相似的合成合並為一個帶有不同屬性的合成

相關資源