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 影片。
注意事項:
- 以下程式碼僅示範如何將影片標籤連接到 HLS 串流,尚未在真實專案中完整測試。
- 使用此方式將影片輸出為 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 的更新通知。
相關連結
- hls.js 官方文件
<Html5Video />— API 文件<OffthreadVideo />— API 文件useRemotionEnvironment()— API 文件- 在預覽與渲染時使用不同元件