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 都很小,組合起來也可能超過限制。解決方案:
- 減少合成數量,使用參數化方式動態生成
- 將相似的合成合並為一個帶有不同屬性的合成