Remotion LabRemotion Lab
其他#t= 媒體片段

#t= 媒體片段

使用 Media Fragments URI 規格,在 Remotion 中以時間範圍精確選取媒體內容。

#t= 媒體片段

Media Fragments URI 是一個 W3C 規格,允許你在 URI 中加入片段識別符(fragment identifier),精確指定要播放媒體的哪個時間段。在 Remotion 中,這個功能讓你可以輕鬆從較長的媒體檔案中擷取特定片段。

基本語法

媒體URL#t=開始時間,結束時間

時間單位為秒(可使用小數點):

video.mp4#t=10        → 從第 10 秒開始播放到結尾
video.mp4#t=10,30     → 播放第 10 秒到第 30 秒的片段
video.mp4#t=,30       → 從頭播放到第 30 秒

在 Remotion 中使用

<Video> 元件

import { Video } from "remotion";
 
export const MyScene: React.FC = () => {
  return (
    <Video
      src="https://example.com/long-video.mp4#t=30,60"
      // 播放影片的第 30 秒到第 60 秒
    />
  );
};

<OffthreadVideo> 元件

import { OffthreadVideo } from "remotion";
 
export const MyScene: React.FC = () => {
  return (
    <OffthreadVideo
      src={`https://example.com/interview.mp4#t=120,180`}
      // 播放第 120 秒到第 180 秒(即 2:00 到 3:00)
    />
  );
};

使用 staticFile() 與本機檔案

import { Video, staticFile } from "remotion";
 
export const MyScene: React.FC = () => {
  return (
    <Video
      src={`${staticFile("footage.mp4")}#t=5,25`}
      // 使用本機檔案的第 5 秒到第 25 秒
    />
  );
};

動態計算片段時間

你可以動態計算片段的時間範圍:

import { Video, staticFile } from "remotion";
 
interface ClipProps {
  startTime: number;
  endTime: number;
}
 
export const VideoClip: React.FC<ClipProps> = ({ startTime, endTime }) => {
  const src = `${staticFile("source.mp4")}#t=${startTime},${endTime}`;
 
  return <Video src={src} />;
};
 
// 使用方式
<VideoClip startTime={15.5} endTime={32.0} />;

搭配 trimStarttrimEnd

Remotion 的 <Video><Audio> 元件也提供 startFromendAt 屬性(以幀為單位),與 #t= 片段類似但以幀數計算:

const fps = 30;
const startSecond = 10;
const endSecond = 30;
 
// 方法一:使用 Media Fragments URI(以秒計算)
<Video src={`video.mp4#t=${startSecond},${endSecond}`} />;
 
// 方法二:使用 startFrom/endAt(以幀計算)
<Video
  src="video.mp4"
  startFrom={startSecond * fps}   // 300 幀
  endAt={endSecond * fps}          // 900 幀
/>;

兩種方式各有適用場景:

  • #t= 語法:直覺、以時間為單位,適合從外部取得時間資訊的場景。
  • startFrom/endAt:以幀為單位,與 Remotion 的時間系統更一致。

使用 getVideoMetadata() 搭配片段

在處理動態時間範圍時,可以先取得影片的總長度,再計算片段:

import { getVideoMetadata } from "@remotion/media-utils";
 
const metadata = await getVideoMetadata("https://example.com/video.mp4");
const totalDuration = metadata.durationInSeconds;
 
// 取影片的中間三分之一
const startTime = totalDuration / 3;
const endTime = (totalDuration * 2) / 3;
 
const fragmentUrl = `https://example.com/video.mp4#t=${startTime},${endTime}`;

音訊的媒體片段

#t= 語法同樣適用於音訊:

import { Audio, staticFile } from "remotion";
 
export const MyScene: React.FC = () => {
  return (
    <>
      {/* 只播放歌曲的副歌部分(第 60 秒到第 90 秒) */}
      <Audio src={`${staticFile("song.mp3")}#t=60,90`} />
    </>
  );
};

注意事項

伺服器支援

使用 #t= 媒體片段時,瀏覽器仍會下載整個檔案(除非伺服器支援 Range Requests)。片段語法只影響播放起始位置,不會讓伺服器只傳送特定部分的資料。

跨瀏覽器相容性

主流瀏覽器(Chrome、Firefox、Safari)都支援 Media Fragments URI,但支援程度有些差異。Remotion 使用的 Chromium 完整支援此規格。

OffthreadVideo 的行為差異

<OffthreadVideo> 在處理媒體片段時,會透過 Remotion 的 FFmpeg 工具鏈進行處理,行為可能與 <Video> 略有不同。若遇到問題,可以嘗試改用 startFrom 屬性替代。

實際應用範例

從訪談影片中擷取精華片段

const highlights = [
  { title: "開場白", start: 5, end: 45 },
  { title: "主要論點", start: 180, end: 240 },
  { title: "結語", start: 520, end: 560 },
];
 
export const HighlightReel: React.FC = () => {
  const { fps } = useVideoConfig();
  const frame = useCurrentFrame();
 
  // 計算目前應播放哪個片段
  // ... 更複雜的邏輯
 
  return (
    <Video
      src={`interview.mp4#t=${highlights[0].start},${highlights[0].end}`}
    />
  );
};

小結

  • #t=開始,結束 語法讓你以秒為單位指定媒體播放範圍。
  • 適用於 <Video><OffthreadVideo><Audio><OffthreadAudio> 元件。
  • 伺服器端仍會下載整個檔案,片段語法只控制播放起始點。
  • 可與 startFrom/endAt 搭配使用,視情況選擇最直觀的方式。