Remotion LabRemotion Lab
Player預掛載元件以實現流暢播放

預掛載元件以實現流暢播放

了解 Remotion 的預掛載(Premounting)機制,透過提前掛載元件讓媒體資源有時間載入,避免播放閃爍。

預掛載元件以實現流暢播放

Remotion 只會渲染當前幀。這意味著當一個影片或其他資源即將出現時,預設情況下它不會被載入。

注意:即使影片即將出現,它也尚未載入,因為 Remotion 只會渲染當前時間點。

什麼是預掛載(Premounting)?

預掛載是一種提前掛載包含資源的元件的做法,讓資源在顯示之前有時間載入。

注意:影片被提前掛載,以便有時間載入。它帶有 opacity: 0 樣式使其不可見。它由 useCurrentFrame() 定義的時間被凍結在 0。

預掛載 <Sequence>

v5.0 開始,所有 <Sequence> 元件預設會預掛載 1 秒(fps 幀)。你可以透過傳遞 premountFor={0} 來停用此行為。

在 v4 中,將 premountFor prop 新增至 <Sequence> 元件以啟用預掛載。你傳遞的數字是元件提前掛載的幀數。

Premounted.tsx
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: 0pointer-events: none 樣式。

使用 layout="none"<Sequence> 無法進行預掛載,因為這樣的序列沒有可以套用樣式的容器。

<Series><TransitionSeries> 搭配使用

premountFor 也可用於 <Series><TransitionSeries>。目前尚無法對整個 <Series><TransitionSeries> 進行預掛載。

自訂預掛載元件

你也可以使用 Remotion 的公開 API 自行實作預掛載。使用以下元件的方式與使用 <Sequence> 相同:

PremountedSequence.tsx
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 秒預掛載對大多數情況已足夠
  • 避免過度使用預掛載,因為它會消耗更多記憶體和頻寬

另請參閱