Remotion LabRemotion Lab
影片HLS 串流支援(HTTP Live Streaming)

HLS 串流支援(HTTP Live Streaming)

在 Remotion 中使用 hls.js 播放 HLS(.m3u8)影片串流,並了解 Chrome v142+ 的原生 HLS 支援現況與注意事項。

HLS 串流支援(HTTP Live Streaming)

Remotion 目前尚未原生支援 HLS / HTTP Live Streaming(.m3u8 格式)。

完整的 HLS 支援將透過 @remotion/media 實現,待 Mediabunny 加入 HLS 支援後即可使用。此議題已被列為高優先項目——您可以在 GitHub issue 追蹤進度。

在預覽時使用 hls.js 播放 HLS 影片

您可以在 <Player> 或 Remotion Studio 的預覽階段使用 hls.js 播放 HLS 影片。

注意事項:

  1. 以下程式碼僅示範如何將影片標籤連接到 HLS 串流,尚未在真實專案中完整測試。
  2. 使用此方式將影片輸出為 MP4 時,音訊將無法正常運作。 請在渲染時改用其他音訊來源。 請參閱「在預覽與渲染時使用不同元件」及 useRemotionEnvironment() 的說明。

安裝 hls.js

npm install hls.js
# 或
yarn add hls.js
# 或
pnpm add hls.js

完整程式碼範例

// HlsDemo.tsx
import Hls from 'hls.js';
import React, { useEffect, useRef } from 'react';
import { AbsoluteFill, RemotionVideoProps, Html5Video } from 'remotion';
 
/**
 * HlsVideo:將 hls.js 與 Html5Video 整合的元件
 * 注意:此元件僅適用於預覽,渲染時請使用其他音訊來源。
 */
const HlsVideo: React.FC<RemotionVideoProps> = ({ src }) => {
  const videoRef = useRef<HTMLVideoElement>(null);
 
  useEffect(() => {
    if (!src) {
      throw new Error('src 為必填屬性');
    }
 
    const startFrom = 0; // 從串流的第幾秒開始載入
 
    // 建立 Hls 實例,設定緩衝限制以避免記憶體過度使用
    const hls = new Hls({
      startLevel: 4,         // 從第 4 個畫質層級開始(較高畫質)
      maxBufferLength: 5,    // 最多預緩衝 5 秒
      maxMaxBufferLength: 5,
    });
 
    // 當 Manifest 解析完成後,開始從指定位置載入
    hls.on(Hls.Events.MANIFEST_PARSED, () => {
      hls.startLoad(startFrom);
    });
 
    // 載入 HLS 來源並綁定至 video 元素
    hls.loadSource(src);
    hls.attachMedia(videoRef.current!);
 
    // 元件卸載時銷毀 Hls 實例,釋放資源
    return () => {
      hls.destroy();
    };
  }, [src]);
 
  return <Html5Video ref={videoRef} src={src} />;
};
 
export const HlsDemo: React.FC = () => {
  return (
    <AbsoluteFill>
      <HlsVideo src="https://stream.mux.com/nqGuji1CJuoPoU3iprRRhiy3HXiQN0201HLyliOg44HOU.m3u8" />
    </AbsoluteFill>
  );
};

在渲染時使用不同來源

由於 HLS 音訊在渲染時無法正常運作,建議搭配 useRemotionEnvironment() 在預覽和渲染時切換不同元件:

import Hls from 'hls.js';
import React, { useEffect, useRef } from 'react';
import {
  AbsoluteFill,
  Html5Video,
  OffthreadVideo,
  RemotionVideoProps,
  useRemotionEnvironment,
} from 'remotion';
 
const HlsVideo: React.FC<RemotionVideoProps> = ({ src }) => {
  const videoRef = useRef<HTMLVideoElement>(null);
 
  useEffect(() => {
    if (!src) return;
 
    const hls = new Hls({
      startLevel: 4,
      maxBufferLength: 5,
      maxMaxBufferLength: 5,
    });
 
    hls.on(Hls.Events.MANIFEST_PARSED, () => {
      hls.startLoad(0);
    });
 
    hls.loadSource(src);
    hls.attachMedia(videoRef.current!);
 
    return () => {
      hls.destroy();
    };
  }, [src]);
 
  return <Html5Video ref={videoRef} src={src} />;
};
 
export const HlsDemoWithFallback: React.FC = () => {
  const { isRendering } = useRemotionEnvironment();
 
  // 渲染時使用靜態 MP4,確保音訊與影像都能正確輸出
  if (isRendering) {
    return (
      <AbsoluteFill>
        <OffthreadVideo src="https://example.com/video.mp4" />
      </AbsoluteFill>
    );
  }
 
  // 預覽時使用 HLS 串流
  return (
    <AbsoluteFill>
      <HlsVideo src="https://stream.mux.com/nqGuji1CJuoPoU3iprRRhiy3HXiQN0201HLyliOg44HOU.m3u8" />
    </AbsoluteFill>
  );
};

Chrome v142+ 的原生 HLS 支援

自 Chrome v142(2025 年 10 月)起,Chrome 瀏覽器支援原生 HLS 播放。

這意味著在 Chrome 瀏覽器中,<OffthreadVideo /> 可以在預覽時直接播放 .m3u8 格式,無需額外設定。

重要限制:原生 HLS 支援目前僅適用於預覽渲染時仍不支援 HLS

import { AbsoluteFill, OffthreadVideo } from 'remotion';
 
// Chrome v142+ 在預覽時可直接使用,但渲染時仍需提供 MP4 備援
export const HlsInChrome: React.FC = () => {
  return (
    <AbsoluteFill>
      <OffthreadVideo
        src="https://stream.mux.com/nqGuji1CJuoPoU3iprRRhiy3HXiQN0201HLyliOg44HOU.m3u8"
      />
    </AbsoluteFill>
  );
};

功能支援矩陣

場景<OffthreadVideo /><Html5Video /> + hls.js<Video /> (@remotion/media)
預覽(Chrome v142+)原生支援需 hls.js規劃中
預覽(其他瀏覽器)不支援需 hls.js規劃中
渲染不支援不支援(音訊問題)規劃中

常見問題

Q:為什麼渲染時 HLS 音訊無法運作?

渲染時 Remotion 使用 Chromium headless 環境,hls.js 的音訊注入方式與渲染管線不相容。目前解法是在渲染時換用靜態 MP4/WebM 來源。

Q:如何知道 @remotion/media 何時支援 HLS?

請追蹤 Remotion GitHub issue 或訂閱 Remotion 的更新通知。

相關連結