Remotion LabRemotion Lab
疑難排解背景圖片閃爍問題

背景圖片閃爍問題

使用 background-image 或 mask-image CSS 屬性時導致渲染閃爍的原因與解決方案

問題說明

在 Remotion 中,下列寫法是不建議的:

// 不建議這樣做
const myMarkup = (
  <div
    style={{
      backgroundImage: `url(${src})`,
    }}
  >
    <p>Hello World</p>
  </div>
);

根本原因

Remotion 在渲染時無法得知圖片是否已完成載入,這是因為透過 background-imagemask-image 或其他 CSS 屬性載入圖片時,無法從外部判斷載入狀態。

由於 Remotion 逐幀獨立渲染,若在圖片尚未載入完成時就截取畫面,就會出現以下問題:

  • 渲染輸出中出現可見的閃爍
  • 部分幀出現空白或未載入的圖片
  • 最終影片品質不一致

解決方案

方法一:改用 <Img> 標籤(推薦)

使用 Remotion 提供的 <Img> 元件搭配 <AbsoluteFill> 來取代 CSS 背景圖片:

import { AbsoluteFill, Img } from "remotion";
 
const myMarkup = (
  <AbsoluteFill>
    {/* 背景圖層 */}
    <AbsoluteFill>
      <Img
        style={{
          width: "100%",
          height: "100%",
          objectFit: "cover",
        }}
        src={src}
      />
    </AbsoluteFill>
    {/* 內容圖層,疊加在圖片上方,不會閃爍 */}
    <AbsoluteFill>
      <p>Hello World</p>
    </AbsoluteFill>
  </AbsoluteFill>
);

<Img> 元件的優點在於 Remotion 能夠追蹤其載入狀態,並在圖片完全載入前暫停渲染,確保每一幀都是完整的。

方法二:使用隱形的 <Img> 作為預載(針對 mask-image 情境)

若你必須使用 mask-image 等 CSS 屬性(例如需要遮罩效果),可以在畫面外渲染一個相同來源的隱形 <Img>,強制 Remotion 等待圖片載入完成:

import { Img } from "remotion";
 
const myMarkup = (
  <>
    {/* 隱形的 Img 用於觸發 Remotion 等待圖片載入 */}
    <Img
      src={src}
      style={{
        opacity: 0,
        position: "absolute",
        width: 1,
        height: 1,
        left: -10000,
      }}
    />
    {/* 實際使用 mask-image 的元素 */}
    <div
      style={{
        maskImage: `url(${src})`,
        maskSize: "cover",
        width: "100%",
        height: "100%",
        backgroundColor: "blue",
      }}
    />
  </>
);

適用範圍

這個問題同樣適用於以下 CSS 屬性:

CSS 屬性說明
background-image設定元素的背景圖片
mask-image設定元素的遮罩圖片
border-image設定元素的邊框圖片
list-style-image設定列表項目的圖示

所有透過 CSS 載入的圖片來源,Remotion 都無法自動追蹤其載入狀態。


延伸閱讀