Remotion LabRemotion Lab
PlayerPlayer 資源預載入

Player 資源預載入

了解如何為 Remotion Player 預載入影片、音訊和圖片資源,使用 @remotion/preload API 和 prefetch() 函式確保媒體在需要時立即可用。

Player 資源預載入

預設情況下,影片、音訊或圖片等資源只會在進入影片畫面時才開始載入。使用 Remotion Player 時,你可能希望提前預載入這些資源,以便在它們進入影片時能立即播放。

目前支援兩種預載入方式:

  1. 使用 @remotion/preload API 向瀏覽器發出載入信號
  2. 使用 prefetch() 提前抓取資源並在本機播放

使用 @remotion/preload 預載入影片

透過預載入,會在頁面上放置一個 <link type='preload'> 標籤,通知瀏覽器可以開始載入該媒體。

  • 影片使用 preloadVideo() API
  • 音訊使用 preloadAudio()
  • 圖片使用 preloadImage()

建議在元件外部或 useEffect() 內部執行預載入:

import { preloadAudio, preloadVideo } from '@remotion/preload';
 
const unpreloadVideo = preloadVideo('https://example.com/video.mp4');
const unpreloadAudio = preloadAudio(
  'https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3'
);
 
// 之後可選擇清理預載入
unpreloadVideo();
unpreloadAudio();

在元件中使用預載入

import { useEffect } from 'react';
import { preloadVideo, preloadAudio } from '@remotion/preload';
import { Player } from '@remotion/player';
import { MyVideo } from './remotion/MyVideo';
 
export const App: React.FC = () => {
  useEffect(() => {
    const unpreloadVideo = preloadVideo('https://example.com/hero-video.mp4');
    const unpreloadAudio = preloadAudio('https://example.com/background-music.mp3');
 
    return () => {
      unpreloadVideo();
      unpreloadAudio();
    };
  }, []);
 
  return (
    <Player
      component={MyVideo}
      durationInFrames={300}
      compositionWidth={1920}
      compositionHeight={1080}
      fps={30}
      controls
    />
  );
};

使用 prefetch() 進行預先抓取

此功能自 v3.2.23 起可用

透過預先抓取,完整的媒體檔案會被下載並使用 URL.createObjectURL() 轉換為 Blob URL。

如果你將原始 URL 傳入 <Audio><Video><OffthreadVideo><Html5Audio><Html5Video><Img> 標籤,且該資源已被預先抓取,這些元件將改用 Blob URL 播放。

import { prefetch } from 'remotion';
 
const { free, waitUntilDone } = prefetch('https://example.com/video.mp4');
 
waitUntilDone().then(() => {
  console.log('影片已完成載入');
});
 
// 如果要取消預先抓取並釋放記憶體,呼叫 free():
free();

在 React 元件中使用 prefetch()

import { useEffect, useState } from 'react';
import { prefetch } from 'remotion';
import { Player } from '@remotion/player';
import { MyVideo } from './remotion/MyVideo';
 
export const App: React.FC = () => {
  const [isReady, setIsReady] = useState(false);
 
  useEffect(() => {
    const { free, waitUntilDone } = prefetch('https://example.com/video.mp4');
 
    waitUntilDone().then(() => {
      setIsReady(true);
    });
 
    return () => {
      free();
    };
  }, []);
 
  return (
    <div>
      {!isReady && <p>預先載入中...</p>}
      <Player
        component={MyVideo}
        durationInFrames={300}
        compositionWidth={1920}
        compositionHeight={1080}
        fps={30}
        controls
      />
    </div>
  );
};

@remotion/preload 與 prefetch() 的比較

prefetch() 是確保媒體在需要時準備就緒的更可靠方式,但需要完整下載資源才能使用。

如果資源較大,@remotion/preload 更為合適,因為你不必等待完整下載。

比較項目preloadAudio() / preloadVideo()prefetch()
適用對象所有音訊和影片 API、圖片與字型<Audio><Video><Html5Audio><Html5Video><Img><OffthreadVideo>
機制插入 <link type='preload'> 標籤抓取資源並轉換為 URL blob 或 Base64 URL
準備就緒條件資源部分載入後即可播放必須完整抓取資源
可靠性不保證,只是向瀏覽器發出信號保證準備就緒,可追蹤載入進度
回呼無法判斷是否已準備就緒Promise resolve 時即代表準備就緒
套件@remotion/preloadremotion
HTTP 重新導向若使用 resolveRedirect(),資源必須支援 CORS自動處理
CORS若使用 resolveRedirect(),資源必須支援 CORS資源必須支援 CORS
可用版本v3.0.14v3.2.23

選擇建議

  • 大型媒體檔案:使用 @remotion/preload,不需要等待完整下載
  • 需要確保準備就緒:使用 prefetch(),可追蹤載入進度並在 Promise resolve 後確認
  • 需要處理 HTTP 重新導向:使用 prefetch(),它會自動處理

預載入 GIF

你可以使用 preloadGif() 預載入並預先解析 GIF:

import { preloadGif } from '@remotion/preload';
 
// 預載入 GIF
const unpreload = preloadGif('https://example.com/animation.gif');
 
// 需要時清理
unpreload();

使用 resolveRedirect() 處理 HTTP 重新導向

若要使用 @remotion/preload 預載入會進行 HTTP 重新導向的資源,你必須先解析重新導向後的 URL:

import { resolveRedirect, preloadVideo } from '@remotion/preload';
import { useEffect } from 'react';
 
export const App: React.FC = () => {
  useEffect(() => {
    let cancel = false;
    let unpreload = () => {};
 
    resolveRedirect('https://example.com/redirecting-video.mp4')
      .then((finalUrl) => {
        if (cancel) return;
        unpreload = preloadVideo(finalUrl);
      })
      .catch(() => {
        // 可能因 CORS 而失敗,此時無法預載入
        if (!cancel) {
          unpreload = preloadVideo('https://example.com/redirecting-video.mp4');
        }
      });
 
    return () => {
      cancel = true;
      unpreload();
    };
  }, []);
 
  return null;
};

相關資源