背景圖片閃爍問題
使用 background-image 或 mask-image CSS 屬性時導致渲染閃爍的原因與解決方案
問題說明
在 Remotion 中,下列寫法是不建議的:
// 不建議這樣做
const myMarkup = (
<div
style={{
backgroundImage: `url(${src})`,
}}
>
<p>Hello World</p>
</div>
);根本原因
Remotion 在渲染時無法得知圖片是否已完成載入,這是因為透過 background-image、mask-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 都無法自動追蹤其載入狀態。