預掛載元件以實現流暢播放
了解 Remotion 的預掛載(Premounting)機制,透過提前掛載元件讓媒體資源有時間載入,避免播放閃爍。
預掛載元件以實現流暢播放
Remotion 只會渲染當前幀。這意味著當一個影片或其他資源即將出現時,預設情況下它不會被載入。
注意:即使影片即將出現,它也尚未載入,因為 Remotion 只會渲染當前時間點。
什麼是預掛載(Premounting)?
預掛載是一種提前掛載包含資源的元件的做法,讓資源在顯示之前有時間載入。
注意:影片被提前掛載,以便有時間載入。它帶有
opacity: 0樣式使其不可見。它由useCurrentFrame()定義的時間被凍結在 0。
預掛載 <Sequence>
從 v5.0 開始,所有 <Sequence> 元件預設會預掛載 1 秒(fps 幀)。你可以透過傳遞 premountFor={0} 來停用此行為。
在 v4 中,將 premountFor prop 新增至 <Sequence> 元件以啟用預掛載。你傳遞的數字是元件提前掛載的幀數。
import { Sequence, staticFile, OffthreadVideo } from 'remotion';
const MyComp: React.FC = () => {
return (
<Sequence from={120} durationInFrames={120} premountFor={100}>
<OffthreadVideo src={staticFile('bigbuckbunny.mp4')} />
</Sequence>
);
};在 Remotion Studio 中,預掛載的元件以斜線條紋標示。
預掛載的 <Sequence> 帶有 opacity: 0 和 pointer-events: none 樣式。
使用 layout="none" 的 <Sequence> 無法進行預掛載,因為這樣的序列沒有可以套用樣式的容器。
與 <Series> 和 <TransitionSeries> 搭配使用
premountFor 也可用於 <Series> 和 <TransitionSeries>。目前尚無法對整個 <Series> 或 <TransitionSeries> 進行預掛載。
自訂預掛載元件
你也可以使用 Remotion 的公開 API 自行實作預掛載。使用以下元件的方式與使用 <Sequence> 相同:
import React, { forwardRef, useMemo } from 'react';
import {
Freeze,
Sequence,
SequenceProps,
useCurrentFrame,
useRemotionEnvironment,
} from 'remotion';
export type PremountedSequenceProps = SequenceProps & {
premountFor: number;
};
const PremountedSequenceRefForwardingFunction: React.ForwardRefRenderFunction<
HTMLDivElement,
PremountedSequenceProps
> = ({ premountFor, ...props }, ref) => {
const frame = useCurrentFrame();
if (props.layout === 'none') {
throw new Error(
'`<PremountedSequence>` does not support layout="none"'
);
}
const env = useRemotionEnvironment();
const { style: passedStyle, from = 0, ...otherProps } = props;
const active =
frame >= from - premountFor && frame < from && !env.isRendering;
const style: React.CSSProperties = useMemo(() => {
return {
...passedStyle,
opacity: active ? 0 : 1,
pointerEvents: active
? 'none'
: (passedStyle?.pointerEvents ?? 'auto'),
};
}, [active, passedStyle]);
return (
<Freeze frame={0} active={active}>
<Sequence from={from} style={style} {...otherProps} ref={ref} />
</Freeze>
);
};
export const PremountedSequence = forwardRef(
PremountedSequenceRefForwardingFunction
);注意:此自訂元件有一個注意事項:在預掛載序列中,原生 buffer 狀態仍可能被觸發。你需要負責在預掛載序列中停用觸發原生 buffer 狀態(例如,將
pauseWhenBuffering設為false)。你可以透過使用 React context 來實現。
與 buffer 狀態搭配使用
如果你也使用 buffer 狀態,<Html5Audio>、<Html5Video>、<OffthreadVideo> 和 <Img> 標籤都能感知預掛載,在預掛載的 <Sequence> 中不會觸發 buffer 狀態。
否則,它會導致在場景甚至尚未可見時就暫停播放。
實際效果對比
未使用預掛載時:當影片序列開始時,資源才開始載入,導致短暫的空白幀或閃爍。
使用預掛載時:影片提前 premountFor 幀被掛載(但不可見),在序列實際開始前,資源已完成載入,播放流暢。
最佳實踐
- 對於包含影片、音訊或大型圖片的序列,建議使用預掛載
- 預掛載時間(幀數)應根據網路環境和資源大小調整
- 在 v5.0 中,預設的 1 秒預掛載對大多數情況已足夠
- 避免過度使用預掛載,因為它會消耗更多記憶體和頻寬