Remotion LabRemotion Lab
疑難排解修復渲染閃爍問題

修復渲染閃爍問題

解釋 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>;
};

您的元件應滿足以下所有條件:

  1. 相同輸入,相同輸出:以相同的幀號呼叫元件,應始終顯示相同的畫面
  2. 不依賴渲染順序:元件不應假設幀是按照順序渲染的
  3. 暫停時靜止不動:當影片暫停時,畫面應保持靜止
  4. 不使用隨機數:除非使用 Remotion 的 random() 函式(它基於幀號生成確定性的隨機值)

暫時繞過多執行緒

如果您的動畫在按順序渲染幀時不會出錯,可以暫時使用 --concurrency=1 旗標:

npx remotion render MyComp out.mp4 --concurrency=1

注意這個方法的限制:

  • 渲染速度會大幅降低
  • 動畫計時仍無法保證完全正確
  • 無法與 Remotion Lambda 一起使用

這只是一個臨時方案,長期應重構程式碼以支援多執行緒渲染。

資產載入問題

原因

Remotion 需要知道資產是否尚未載入,才能在截圖前等待載入完成。如果不正確處理,Remotion 可能會對「載入中」狀態截圖,導致閃爍或空白幀。

解決方案

  1. 使用 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")} />
  2. 獲取資料時使用 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>;
    };
  3. 確保字型已載入後再使用

    在呼叫 fitText()fillTextBox()measureText() 之前,務必等待字型載入完成。

  4. 避免使用 background-imagemask-image CSS 屬性

    這些 CSS 屬性無法被 Remotion 追蹤載入狀態,改用 <Img> 元件替代。

<Html5Video> 標籤的閃爍問題

同時加入大量 <Html5Video> 標籤可能導致渲染卡頓。如果遇到此問題,考慮改用其他影片標籤以達到逐幀精確渲染。

第三方整合

如果您使用第三方動畫函式庫(例如 GSAP、Lottie 等),查看 第三方整合清單,確認是否有同步動畫與 useCurrentFrame() 的解決方案。

為什麼 Remotion 採用這種設計

渲染速度對於伺服器端渲染非常重要。按順序逐幀渲染的速度代價過高,而採用能支援並行渲染的程式碼撰寫方式,可以在不犧牲品質的情況下大幅提升速度。

設定 --concurrency=1 雖然看起來「修復」了閃爍問題,但實際上只是因為渲染速度恰好接近動畫速度而湊巧看起來正常。真正的時序同步並不存在,在不同機器上的結果也可能不同。

確定性的影片還能支援分散式渲染(例如 Remotion Lambda),其渲染速度可以遠超過實時速度。

參見