Remotion LabRemotion Lab
影片staticFile() 函式

staticFile() 函式

使用 staticFile() 將 public/ 資料夾中的檔案轉換為可在 Remotion 中載入的 URL,安全地引用靜態資源。

什麼是 staticFile()

staticFile() 是 Remotion v2.5.7 引入的函式,它將你 public/ 資料夾中的檔案轉換成一個可在專案中載入的 URL

import { Img, staticFile } from "remotion";
 
const myImage = staticFile(`/my-image.png`);
 
// ...
<Img src={myImage} />;

如何使用

第一步:建立 public/ 資料夾

在你的影片專案根目錄建立一個 public/ 資料夾:

my-video/
├─ node_modules/
├─ public/
│  ├─ my-image.png
│  ├─ font.woff2
├─ src/
│  ├─ Root.tsx
│  ├─ index.ts
├─ package.json

重要public/ 資料夾應始終與包含 remotion 依賴的 package.json 放在同一個資料夾中,即使你的 Remotion 程式碼位於子目錄中也是如此。

第二步:取得資源的 URL 參照

import { staticFile } from "remotion";
 
const myImage = staticFile(`/my-image.png`);
// "/static-32e8nd/my-image.png"
 
const font = staticFile(`/font.woff2`);
// "/static-32e8nd/font.woff2"

第三步:載入資源

你可以透過以下方式載入資源:

  • <Img><Audio><Video><OffthreadVideo><Html5Audio><Html5Video> 標籤
  • Fetch API
  • FontFace()
  • 任何其他支援透過 URL 進行資料獲取的載入器

為什麼不能直接使用字串路徑?

如果你曾使用過 Create React App 或 Next.JS,可能習慣直接用字串參照資源:

<!-- 在其他框架中這樣做 -->
<img src="/my-image.png" />

但 Remotion 選擇使用 staticFile() API,原因如下:

  1. 防止部署到子目錄時失效:若你的網站部署在 https://example.com/my-folder/,直接使用 /my-image.png 會導致路徑錯誤,而 staticFile() 會確保路徑正確。

  2. 避免與 Composition 名稱衝突:若你有一個名為 my-video 的 Composition,它可能與 http://localhost:3000/my-video 的靜態資源路徑產生衝突。staticFile() 使用特殊前綴(如 /static-32e8nd/)來避免這種情況。

  3. 讓路徑跨框架相容:這使你的程式碼可以在 Remotion、Create React App、Next.JS 等不同框架中運作。

取得所有靜態檔案列表

使用 getStaticFiles() API 來取得 public/ 資料夾中所有可用檔案的列表:

import { getStaticFiles } from "remotion";
 
const files = getStaticFiles();
// 回傳所有 public/ 資料夾中的檔案列表

處理含有特殊字元的檔名 v4.0.0

從 v4.0 起,staticFile() 會使用 encodeURIComponent 對檔名進行編碼。

重要:如果你之前自己進行過編碼,升級到 v4.0 後請確保不要再自行編碼,以避免雙重編碼。

v4.0 之前的行為

// v4.0 之前
staticFile("my-image#portrait.png");
// 輸出:"/my-image#portrait.png"

若將此 URL 傳給接受 URL 的元件,# 之後的部分會被忽略,導致找不到檔案。

v4.0.0 之後的行為

// v4.0.0 之後
staticFile("my-image#portrait.png");
// 輸出:"/my-image%23portrait.png"

現在圖片能正確載入。但你必須避免自行對檔名進行編碼,否則會造成雙重編碼:

// 錯誤做法:自行編碼後再傳入
staticFile(encodeURIComponent("my-image#portrait.png"));
// 輸出:"/my-image%2523portrait.png"(雙重編碼,會出錯)
 
// 正確做法:直接傳入原始檔名
staticFile("my-image#portrait.png");
// 輸出:"/my-image%23portrait.png"(正確)

實際應用範例

載入圖片

import { AbsoluteFill, Img, staticFile } from "remotion";
 
export const MyComp: React.FC = () => {
  return (
    <AbsoluteFill>
      <Img src={staticFile("background.png")} />
    </AbsoluteFill>
  );
};

載入影片

import { AbsoluteFill, OffthreadVideo, staticFile } from "remotion";
 
export const MyComp: React.FC = () => {
  return (
    <AbsoluteFill>
      <OffthreadVideo src={staticFile("clip.mp4")} />
    </AbsoluteFill>
  );
};

載入自訂字型

import { staticFile } from "remotion";
import { useEffect } from "react";
 
export const useCustomFont = () => {
  useEffect(() => {
    const font = new FontFace(
      "MyFont",
      `url(${staticFile("my-font.woff2")})`
    );
    font.load().then((loadedFont) => {
      document.fonts.add(loadedFont);
    });
  }, []);
};

用 Fetch API 載入 JSON 資料

import { delayRender, continueRender, staticFile } from "remotion";
import { useState, useEffect } from "react";
 
export const MyComp: React.FC = () => {
  const [data, setData] = useState(null);
  const [handle] = useState(() => delayRender());
 
  useEffect(() => {
    fetch(staticFile("data.json"))
      .then((res) => res.json())
      .then((json) => {
        setData(json);
        continueRender(handle);
      });
  }, [handle]);
 
  if (!data) return null;
 
  return <div>{JSON.stringify(data)}</div>;
};

相容性

環境使用前綴支援
Chrome/
Firefox/
Safari/
Node.js/
Bun/
Serverless Functions/
客戶端渲染/
伺服器端渲染/
Player/
Studio/

相關資源