流媒体 HLS 协议介绍
HLS(HTTP Live Streaming) 是由 Apple 推出的一种基于 HTTP 的流媒体传输协议。它将音视频文件切片为多个小的 .ts
媒体文件,并通过 .m3u8
播放列表文件进行索引和调度。由于其兼容性好、支持 CDN 加速、可自适应码率,因此广泛用于点播和直播场景中。类似的还有 DASH 协议,相关参数对比如下:
| 特性维度
|
HLS(HTTP Live Streaming)
|
DASH(Dynamic Adaptive Streaming over HTTP)
Apple 私有协议
|
国际标准(MPEG)
| | 封装格式 |
传统使用 MPEG-TS
现代支持 fMP4
|
主流使用 fMP4
|
| 播放列表格式 | .m3u8
(M3U8 格式)
| .mpd
(XML 格式)
| | 延迟表现 |
相对较高(常见 6~30 秒)
|
相对较低(2~15 秒)
| | 码率自适应 |
支持(多码率播放列表)
|
支持(更灵活)
| | 加密方式 |
支持 AES-128,FairPlay
|
支持 Widevine、PlayReady、FairPlay 等
| | 浏览器兼容性 |
原生支持 Safari,其他需配合 hls.js
|
原生支持 Chrome、Edge(支持 MSE)
| | 跨平台表现 |
Apple 系统兼容性好
|
更具通用性、跨平台标准广泛
| | 播放器支持 |
Safari、QuickTime、hls.js
、video.js
|
Dash.js、Shaka Player、Bitmovin 等
| | 协议灵活性 |
略低(Apple 控制标准)
|
高(开放标准,扩展性强)
|
HLS 协议交互流程
1. 主播放列表(main.m3u8)
客户端基于 hls.js
库向服务端请求主播放列表,服务端返回内容如下:
#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360 low/index.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1400000,RESOLUTION=1280x720 mid/index.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2800000,RESOLUTION=1920x1080 high/index.m3u8
字段说明:
-
#EXTM3U
:标志该文件为 M3U8 文件。 -
#EXT-X-STREAM-INF
:表示接下来的 URI 指向一个媒体播放列表。 -
BANDWIDTH
:码率(单位 bit/s),用于自适应码率选择。 -
RESOLUTION
:视频分辨率(宽 x 高)。
客户端解析 playlist 内容后,根据当前的网络情况、设备类型等因素,再请求具体的媒体播放列表。
2. 媒体播放列表(media.m3u8)
示例内容:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:9.984, fileSequence0.ts #EXTINF:10.000, fileSequence1.ts #EXTINF:10.000, fileSequence2.ts #EXT-X-ENDLIST
上述媒体播放列表内容中,最重要的就是 EXTINF
和紧接着下面一行的视频片段 url。比如第一次出现的 #EXTINF:9.984
,表示第一个片段时长 9.984 秒,且这个视频片段的 url 是 fileSequence0.ts
。在播放过程中,可以根据当前播放进度自动匹配出要播放哪个视频片段,且通常会预请求当前播放时间点后面的 n 个片段,以保证播放更流畅。
字段说明:
| 标签
|
描述
M3U8 文件开头标识
|
| #EXT-X-VERSION
|
HLS 协议版本(可选)
|
| #EXT-X-TARGETDURATION
|
每个片段的最大时长(单位:秒)
|
| #EXT-X-MEDIA-SEQUENCE
|
播放列表中第一个媒体段的序号
|
| #EXTINF:<duration>,
|
下一个媒体文件的持续时间(单位:秒)
|
| fileSequenceN.ts
|
媒体片段的文件路径或 URL
|
| #EXT-X-ENDLIST
|
表明播放列表已经结束(仅点播使用)
|
HLS 点播与直播的区别
HLS 协议有 2 种模式,一种是点播模式(VOD),一种是直播模式(Live)。点播模式就像国内爱优腾这种流媒体视频(有兴趣可以打开控制台 network 看看是不是用了 hls 协议)。这 2 种模式的区别如下:
| 特性
|
点播(VOD)
|
直播(Live)
是否包含 #EXT-X-ENDLIST
|
是
|
否
|
| .m3u8
是否更新
|
固定不变
|
实时更新
| |
播放列表是否包含所有片段
|
是
|
只包含最近一段时间的片段
| |
是否有完整媒体时长
|
有
|
无
|
如何分割 hls 视频片段
使用 ffmpeg 工具,可以一行命令将视频分割成 hls 视频片段,并自动生成 m3u8 播放列表清单,示例命令如下:
ffmpeg -i input.mp4 \ -codec: copy \ -start_number 0 \ -hls_time 10 \ -f hls output.m3u8
总结
HLS 是一种非常主流的流媒体传输协议,大部分的流媒体视频都使用该协议来播放。凭借良好的兼容性和成熟的生态,广泛应用于点播、直播等场景。但是 HLS 目前还是存在直播延迟大的问题,也许 DASH 协议才是未来主流?