背景:为什么 HLS 延迟这么高?
标准 HLS 的工作流程是:编码器输出 → 切成 6 秒一个 ts → 写入 m3u8 → 播放器拉取播放。播放器需要至少 3 个切片才能稳定起播,加上预加载和网络抖动缓冲,端到端延迟通常在 15~30 秒。
导致高延迟的几个因素:
- 切片时间过长(
hls_fragment通常 6s) - 播放器需要缓存 3 个切片才开播
- 客户端策略只拉取 playlist 末尾第二或第三个分片
LL-HLS 是怎么做到低延迟的
Apple 在 HLS v7 规范中引入了 LL-HLS(Low-Latency HLS),核心思路有三:
- Partial Segments(部分切片):每个 ts 切片还可以再切成更小的 part(200ms~500ms),播放器边出边拉。
- Blocking Reload:客户端发起 playlist 请求时带
_HLS_msn/_HLS_part,服务端 hold 住连接直到新分片产生。 - Playlist Delta Updates:用
#EXT-X-SKIP增量更新,减少 m3u8 体积。
效果:开启 LL-HLS 后,端到端延迟可压到 2 秒以内,接近 HTTP-FLV 体验,同时保留 HLS 的 CDN 友好特性。
SRS 服务端配置
SRS 5.0+ 已原生支持 LL-HLS,配置 conf/srs.conf:
http_server {
enabled on;
listen 8080;
dir /usr/local/srs/htdocs;
}
vhost __defaultVhost__ {
hls {
enabled on;
hls_path /usr/local/srs/htdocs;
hls_fragment 2s; # 切片长度
hls_window 6s; # playlist 长度
hls_ts_file live/test-%d.ts;
hls_m3u8_file live/test.m3u8;
# LL-HLS 关键参数
hls_ctx 6s;
hls_aof 2s;
# 启用部分切片
hls_partial on;
}
}
推流测试:
ffmpeg -re -i input.mp4 -c:v libx264 -preset veryfast -tune zerolatency \
-bf 0 -g 30 -keyint_min 30 -sc_threshold 0 \
-c:a aac -b:a 128k \
-f flv rtmp://127.0.0.1:1935/live/test
注意:必须关闭 B 帧(
-bf 0),并强制 GOP 等于帧率,否则 LL-HLS 部分切片无法生成。
hls.js 客户端联调
hls.js 1.0+ 已支持 LL-HLS,开启低延迟模式:
<video id="v" controls autoplay></video>
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<script>
const v = document.getElementById('v');
if (Hls.isSupported()) {
const hls = new Hls({
lowLatencyMode: true, // 关键:开启 LL-HLS
backBufferLength: 30,
maxBufferLength: 6,
maxMaxBufferLength: 6,
liveSyncDuration: 1.5,
liveMaxLatencyDuration: 5,
enableWorker: true
});
hls.loadSource('http://example.com/live/test.m3u8');
hls.attachMedia(v);
hls.on(Hls.Events.MANIFEST_PARSED, () => v.play());
} else if (v.canPlayType('application/vnd.apple.mpegurl')) {
v.src = 'http://example.com/live/test.m3u8';
v.play();
}
</script>
打开浏览器 Network 面板,你会看到大量 test-1.ts?_HLS_part=0 这样的小请求,说明部分切片已生效。
总结
- 标准 HLS 延迟 15~30s,适合点播或对实时性要求不高的直播
- LL-HLS 通过部分切片 + 阻塞请求,延迟可压到 2s 以内
- SRS + hls.js + 关闭 B 帧是最小可用组合
- 再低就要上 WebRTC(端到端 0.5s)
下次我们聊聊怎么用 WebRTC + SRS 进一步把延迟打到 500ms 以内,敬请关注。