跳转到内容

HLS 服务器 - Monibuca 流媒体分发

HLS(HTTP Live Streaming)是 Apple 提出的基于 HTTP 的流媒体协议。通过将直播流切割为 TS 片段并生成 M3U8 播放列表,HLS 具有极佳的 CDN 兼容性和设备覆盖率,是大规模分发的首选协议。

属性
传输层HTTP(共享引擎 HTTP 端口)
推流❌ 不支持
拉流✅ 支持
延迟5-30 秒(取决于切片时长)
配置节hls

预编译二进制已内置该插件,在 config.yaml 中配置即可:

hls:
enable: true
segment_duration: 6
max_segments: 5
output_dir: "./hls"
write_to_disk: true
配置项类型默认值说明
enablebooltrue是否启用 HLS 插件
segment_durationu646TS 切片时长(秒)
max_segmentsusize5播放列表保留的最大切片数
output_dirstring"./hls"切片文件输出目录
write_to_diskbooltrue是否将切片写入磁盘
dvr_windowu320按时长保留的 DVR/回看窗口(秒);0 = 关闭。与 max_segments(直播短尾)独立

默认 dvr_window: 0,行为与原先一致:直播播放列表只保留 max_segments 个切片。

设置 dvr_window(秒)后,已完成的切片会按累计时长在本节点额外保留,不改写普通直播播放列表。玩家通过查询参数选择回看视图:

查询行为
(无)或 _HLS_rewind=NO当前直播短尾(与关闭 DVR 时字节级一致)
_HLS_rewind=YESEXT-X-PLAYLIST-TYPE:EVENT,覆盖保留窗口内已完成切片(含正确的 MEDIA-SEQUENCE / discontinuity;LL-HLS 时含已完成 PART)
hls:
enable: true
write_to_disk: true # DVR 必需;否则打 warning 并视为关闭
max_segments: 5 # 直播短尾(不变)
dvr_window: 120 # 额外保留约 2 分钟
# 直播
GET /hls/live/show/index.m3u8
# 回看(EVENT)
GET /hls/live/show/index.m3u8?_HLS_rewind=YES

ABR:在 master 上带 _HLS_rewind=YES 时,会把该查询传播到各档位媒体 URI;各档位 remuxer 独立按时长保留。

已保留的 DVR 切片可以原子导出为稳定的 HLS VoD 资产:

Terminal window
curl -X POST "http://localhost:8180/hls/api/dvr/export" \
-H "Content-Type: application/json" \
-d '{
"stream_path": "live/show",
"start": 120,
"end": 135,
"name": "show-highlight"
}'

请求字段:

字段说明
stream_path源直播流路径
start / endHLS EXT-X-MEDIA-SEQUENCE 范围,包含两端;必须仍在本节点 dvr_window 保留窗口内
name可选资产名;省略时自动生成

响应会返回 playlist_url,例如:

{
"status": "ok",
"playlist_url": "/hls/vod/show-highlight/index.m3u8",
"segment_count": 16,
"duration": 48.0
}

导出时会先把选中的 .ts 切片硬链接到录制目录(跨文件系统失败时自动复制),写入临时 index.m3u8.tmp 后原子重命名为 index.m3u8。导出完成后,直播 DVR 清理不会影响该 VoD 资产。播放地址仍走 HLS 鉴权:

Terminal window
ffplay http://localhost:8180/hls/vod/show-highlight/index.m3u8

默认 abr: [](或不写 abr)时,行为与单码率一致:每个流路径只提供一份媒体播放列表。配置 hls.abr 后,可为逻辑主路径生成 multivariant master playlist,指向各档位的媒体 index.m3u8

HLS 插件只组装 master;各档位码流需由 transcode 插件onpub 输出(或其他方式)发布为独立子流后再由 HLS remux。

hls:
enable: true
abr:
- master: live/show
renditions:
- path: live/show_720p
bandwidth: 2500000
resolution: "1280x720"
codecs: "avc1.64001f,mp4a.40.2" # 可选
- path: live/show_480p
bandwidth: 1200000
resolution: "854x480"
字段说明
master逻辑主路径,对应 master URL 中的 {streamPath}
renditions有序档位(建议高码率在前)
path该档位媒体播放列表对应的流路径
bandwidth#EXT-X-STREAM-INF:BANDWIDTHbps,必填且 > 0)
resolution可选,如 1280x720
codecs可选,RFC 6381 字符串

规范地址:

GET /hls/<master>/master.m3u8

示例:http://localhost:8180/hls/live/show/master.m3u8

当该 master 已配置 ABR 时,/hls/<master>/index.m3u8/hls/<master>.m3u8 也会返回同一份 multivariant playlist(便于兼容旧客户端);规范入口仍是 master.m3u8。各档位媒体列表仍为 /hls/<rendition>/index.m3u8

端到端示例(RTMP → 转码 → ABR)

Section titled “端到端示例(RTMP → 转码 → ABR)”
  1. 推流:ffmpeg -re -i input.mp4 -c copy -f flv rtmp://localhost:1935/live/show
  2. Transcode onpub 生成 live/show_720p / live/show_480p(见 转码插件
  3. 配置上方 hls.abr
  4. 播放器打开 master:
Terminal window
ffplay http://localhost:8180/hls/live/show/master.m3u8

完整 YAML 片段:

transcode:
enable: true
onpub:
"^live/show$":
outputs:
- target: "rtmp://127.0.0.1/live/show_720p"
options:
video_codec: "libx264"
resolution: "1280x720"
video_bitrate: 2500
audio_codec: "aac"
audio_bitrate: 128
- target: "rtmp://127.0.0.1/live/show_480p"
options:
video_codec: "libx264"
resolution: "854x480"
video_bitrate: 1200
audio_codec: "aac"
audio_bitrate: 96
hls:
enable: true
abr:
- master: live/show
renditions:
- path: live/show_720p
bandwidth: 2500000
resolution: "1280x720"
codecs: "avc1.64001f,mp4a.40.2"
- path: live/show_480p
bandwidth: 1200000
resolution: "854x480"
http://host:port/hls/{streamPath}/index.m3u8

ABR master(已配置时):

http://host:port/hls/{masterPath}/master.m3u8
http://host:port/hls/{streamPath}/{sequence}.ts

示例:

http://localhost:8180/hls/live/test/index.m3u8
http://localhost:8180/hls/live/test/0.ts
Terminal window
ffplay http://localhost:8180/hls/live/test/index.m3u8
  1. 打开 VLC,选择 媒体打开网络串流
  2. 输入 URL:http://localhost:8180/hls/live/test/index.m3u8
  3. 点击 播放

使用 hls.js 在浏览器中播放:

<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="player" controls></video>
<script>
const video = document.getElementById('player');
if (Hls.isSupported()) {
const hls = new Hls();
hls.loadSource('http://localhost:8180/hls/live/test/index.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED, () => video.play());
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
// Safari 原生支持
video.src = 'http://localhost:8180/hls/live/test/index.m3u8';
video.play();
}
</script>

HLS 插件提供录制 API,可以将流录制为 HLS 格式(M3U8 + TS 文件):

录制播放列表在录制期间保持开放,停止时才写入 EXT-X-ENDLIST;所有已完成切片都会保留,不受直播 max_segments 滑动窗口限制。长时间录制前请规划并监控磁盘容量。

Terminal window
# 开始录制
curl -X POST http://localhost:8180/hls/record/start/live/test
# 停止录制
curl -X POST http://localhost:8180/hls/record/stop/live/test
# 查看录制列表
curl http://localhost:8180/hls/record/list
# 查看录制状态
curl http://localhost:8180/hls/record/status/live/test
# 查询历史录像
curl http://localhost:8180/hls/record/records
  1. 订阅流:当首次请求 HLS 播放列表时,插件自动订阅对应的流
  2. 切片生成:从流中持续读取帧数据,按 segment_duration 切割为 TS 片段
  3. 播放列表更新:每生成一个新切片,自动更新 M3U8 播放列表
  4. 滑动窗口:保留最近 max_segments 个切片,旧切片自动清理
  5. 存储策略:切片同时保存在内存和磁盘(取决于 write_to_disk 配置)

HLS 的延迟主要由以下因素决定:

总延迟 ≈ segment_duration × (max_segments - 1) + 播放器缓冲

优化建议:

# 低延迟配置
hls:
segment_duration: 2
max_segments: 3

此配置下理论最低延迟约 4-6 秒。

Terminal window
# 1. 通过 RTMP 推流
ffmpeg -re -i input.mp4 -c copy -f flv rtmp://localhost:1935/live/test
# 2. 通过 HLS 拉流
ffplay http://localhost:8180/hls/live/test/index.m3u8
# 3. 也可以同时通过其他协议拉流
ffplay http://localhost:8180/flv/live/test.flv

联系我们

微信公众号:不卡科技 微信公众号二维码
腾讯频道:流媒体技术 腾讯频道二维码
QQ 频道:p0qq0crz08 QQ 频道二维码
QQ 群:751639168 QQ 群二维码