修復渲染閃爍問題
解釋 Remotion 渲染中出現畫面閃爍或不連續的原因,以及如何透過正確的動畫架構和資產載入方式解決問題
修復渲染閃爍問題
問題說明
如果您的 Remotion 影片在預覽時看起來很流暢,但渲染後出現閃爍或畫面不連續的問題,本文將幫助您診斷並解決這些問題。
多執行緒問題
原因
Remotion 的工作方式如下:為了大幅加快渲染速度,它會同時開啟多個瀏覽器分頁來渲染影片。這些分頁不共享狀態,因此任何不依賴 useCurrentFrame() 的動畫都會在不同分頁中產生不一致的結果,導致渲染後出現閃爍。
解決方案
將您的元件設計為純函式,讓動畫完全由 useCurrentFrame() 的值驅動:
import { useCurrentFrame } from "remotion";
// 正確做法:動畫完全依賴 frame 值
export const MyAnimation = () => {
const frame = useCurrentFrame();
const opacity = frame / 30; // 前 30 幀從 0 淡入到 1
return <div style={{ opacity }}>Hello</div>;
};您的元件應滿足以下所有條件:
- 相同輸入,相同輸出:以相同的幀號呼叫元件,應始終顯示相同的畫面
- 不依賴渲染順序:元件不應假設幀是按照順序渲染的
- 暫停時靜止不動:當影片暫停時,畫面應保持靜止
- 不使用隨機數:除非使用 Remotion 的
random()函式(它基於幀號生成確定性的隨機值)
暫時繞過多執行緒
如果您的動畫在按順序渲染幀時不會出錯,可以暫時使用 --concurrency=1 旗標:
npx remotion render MyComp out.mp4 --concurrency=1注意這個方法的限制:
- 渲染速度會大幅降低
- 動畫計時仍無法保證完全正確
- 無法與 Remotion Lambda 一起使用
這只是一個臨時方案,長期應重構程式碼以支援多執行緒渲染。
資產載入問題
原因
Remotion 需要知道資產是否尚未載入,才能在截圖前等待載入完成。如果不正確處理,Remotion 可能會對「載入中」狀態截圖,導致閃爍或空白幀。
解決方案
-
使用 Remotion 提供的媒體元件
這些元件內建了等待資產載入的機制:
import { Img, Video, OffthreadVideo, Audio, Iframe } from "remotion"; import { Gif } from "@remotion/gif"; // 這些元件會自動等待資產載入完成 <Img src={staticFile("image.png")} /> <Video src={staticFile("video.mp4")} /> <Audio src={staticFile("audio.mp3")} /> -
獲取資料時使用
delayRender()import { delayRender, continueRender } from "remotion"; import { useEffect, useState } from "react"; export const MyComp = () => { const [data, setData] = useState(null); const [handle] = useState(() => delayRender()); useEffect(() => { fetch("https://api.example.com/data") .then((res) => res.json()) .then((result) => { setData(result); continueRender(handle); }); }, []); return <div>{data ? data.title : "載入中..."}</div>; }; -
確保字型已載入後再使用
在呼叫
fitText()、fillTextBox()或measureText()之前,務必等待字型載入完成。 -
避免使用
background-image和mask-imageCSS 屬性這些 CSS 屬性無法被 Remotion 追蹤載入狀態,改用
<Img>元件替代。
<Html5Video> 標籤的閃爍問題
同時加入大量 <Html5Video> 標籤可能導致渲染卡頓。如果遇到此問題,考慮改用其他影片標籤以達到逐幀精確渲染。
第三方整合
如果您使用第三方動畫函式庫(例如 GSAP、Lottie 等),查看 第三方整合清單,確認是否有同步動畫與 useCurrentFrame() 的解決方案。
為什麼 Remotion 採用這種設計
渲染速度對於伺服器端渲染非常重要。按順序逐幀渲染的速度代價過高,而採用能支援並行渲染的程式碼撰寫方式,可以在不犧牲品質的情況下大幅提升速度。
設定 --concurrency=1 雖然看起來「修復」了閃爍問題,但實際上只是因為渲染速度恰好接近動畫速度而湊巧看起來正常。真正的時序同步並不存在,在不同機器上的結果也可能不同。
確定性的影片還能支援分散式渲染(例如 Remotion Lambda),其渲染速度可以遠超過實時速度。