避免 Player 閃爍問題
了解為什麼 Remotion Player 會出現閃爍現象,以及多種不同程度的解決策略。
避免 <Player> 的閃爍問題
請考慮以下標記:
import { AbsoluteFill, Sequence, OffthreadVideo } from 'remotion';
const MyComponent: React.FC = () => {
return (
<AbsoluteFill>
<Sequence from={0} durationInFrames={120}>
<OffthreadVideo src="https://example.com/video1.mp4" />
</Sequence>
<Sequence from={120} durationInFrames={120}>
<OffthreadVideo src="https://example.com/video2.mp4" />
</Sequence>
</AbsoluteFill>
);
};由於 Remotion 只感知當前幀,來源為 video2.mp4 的影片只會在它開始出現在場景中時才開始載入。這可能在 Player 中導致某些幀為空白的效果,因為影片的載入通常不會立即完成。
這是 Remotion 的設計取捨,但可以透過不同程度的方式來應對。
解決策略
策略一:忽略
此效果只發生在 Remotion Studio 和 Remotion Player 中,不會出現在渲染後的影片中。如果你只需要逐幀完美的渲染影片,不需要採取額外步驟。
策略二:在媒體緩衝時暫停 <Player>
建議做法:此功能將在 Remotion 5.0 成為預設行為。
你可能希望暫時暫停 <Player> 以允許資源載入,並在資源準備好可以播放後恢復。
你可以透過將 pauseWhenBuffering prop 新增至 <Html5Audio>、<Html5Video>、<OffthreadVideo> 和 <Img> 標籤來實現。了解更多關於 buffer 狀態的資訊。
import { OffthreadVideo, Sequence, staticFile } from 'remotion';
const MyComp: React.FC = () => {
return (
<Sequence from={120} durationInFrames={120}>
<OffthreadVideo
src={staticFile('video2.mp4')}
pauseWhenBuffering
/>
</Sequence>
);
};注意:
pauseWhenBufferingprop 在@remotion/media的<Video>和<Audio>中預設為啟用。
策略三:預掛載影片
建議做法:這是最有效的解決方案。
你可以比序列開始顯示的時間提前幾幀掛載它,使其有時間在使用者看到之前載入,這有助於避免閃爍。
詳情請參閱預掛載(Premounting)。
import { Sequence, OffthreadVideo, staticFile } from 'remotion';
const MyComp: React.FC = () => {
return (
// 提前 60 幀預掛載
<Sequence from={120} durationInFrames={120} premountFor={60}>
<OffthreadVideo src={staticFile('video2.mp4')} />
</Sequence>
);
};策略四:預載入以避免網路請求
建議做法:這有助於減少網路載入時間。
你可以向瀏覽器發出預載入影片和其他資源的信號,讓嵌入元素出現在影片中時,可以省去網路請求的時間。
詳情請參閱預載入(Preloading)。
注意:你向瀏覽器發出的信號可能會被忽略,例如裝置啟用了省流量或省電模式時。這對行動裝置尤為值得注意。
策略五:預取(Prefetch)為 Blob URL 以更積極地避免網路請求
不建議:記憶體密集,且只有在 Player 掛載前完成預取才有用,且常被誤用。
透過預取(prefetch)資源,它將被下載並快取至記憶體中。與預載入不同,你強制瀏覽器下載資源,但只有在資源完全下載後才能使用。
完全下載後,媒體標籤中的 URL 將被替換為 Blob URL。你必須確保不在播放途中替換 URL,否則播放可能會變差。
只有在媒體元素掛載之前完成預取才有意義。
注意:即使是預載入的資源或預取的資源,也需要掛載至 DOM 並由瀏覽器解碼,這可能需要短暫的時間。
策略六:預取為 Base64 以避免網路請求和本地 HTTP 伺服器
不建議:與預取有相同缺點,但還有額外的效能損耗,特別是對於大型資源。
在 Safari 中,策略五中描述的預取不夠充分,因為 Blob URL 會被儲存到磁碟,即使資源已預儲,仍可能發生輕微延遲。
另外,prefetch() 函式允許以 Base64 格式將資源取回並儲存在記憶體中,不需要透過 HTTP 從磁碟載入 Blob URL。
import { prefetch } from 'remotion';
// 以 Base64 格式預取資源
const { free } = prefetch('https://example.com/video2.mp4', {
method: 'base64',
});
// 不再需要時釋放記憶體
// free();策略比較
| 策略 | 效果 | 推薦程度 | 備註 |
|---|---|---|---|
| 忽略 | 無 | 適用於只需渲染影片 | 只影響預覽 |
| 緩衝時暫停 | 高 | 強烈推薦 | 將成為 v5.0 預設行為 |
| 預掛載 | 高 | 強烈推薦 | 最有效的解決方案 |
| 預載入 | 中 | 推薦 | 減少網路請求時間 |
| Blob 預取 | 高 | 不推薦 | 記憶體密集,容易誤用 |
| Base64 預取 | 高 | 不推薦 | 效能損耗大 |