音视频文件提供流式传输之HTTP Live Streaming (HLS)
HTTP Live Streaming (HLS) 是由 Apple 推出的基于 HTTP 的流媒体协议,它通过将音视频文件切分成一系列较小的分段文件,并通过 M3U8 播放列表进行索引,使得音视频可以实现流式传输,支持动态适应不同带宽的自适应流媒体传输。
HLS 是广泛使用的流媒体协议,特别适用于视频点播和直播服务。在音视频文件的流式传输中,HLS 的优点包括:无需专门的流媒体服务器,支持设备和平台的广泛兼容,以及通过分段传输来实现内容的快速加载。
1. HLS 工作原理
HLS 将音视频内容分割为多个小的 .ts
(MPEG-TS) 文件(通常几秒钟的时长),并通过一个 .m3u8
播放列表文件索引这些分段。客户端根据网络带宽选择不同质量的分段进行播放,从而实现自适应比特率流。
HLS 主要组件:
- 视频分段文件 (.ts):音视频流被切割为多个短小的文件(通常是 5 到 10 秒),每个文件包含音视频数据的一部分。
- 播放列表文件 (.m3u8):是一个索引文件,列出所有的分段文件的位置。播放列表文件可以是主播放列表(包含不同分辨率、比特率的流),也可以是媒体播放列表(指向具体的
.ts
文件)。
流程:
- 视频编码:视频内容首先进行编码(如 H.264 视频编码,AAC 音频编码),然后将其分段成多个
.ts
文件。 - 生成播放列表 (M3U8):每个分段的
.ts
文件会被列出在一个.m3u8
播放列表文件中。可以有多个.m3u8
播放列表文件,分别对应不同的码率(低、中、高质量等)。 - 客户端请求播放:客户端(如浏览器、移动设备)请求
.m3u8
文件,解析该文件后获取音视频分段,并开始请求对应的.ts
分段进行播放。
2. HLS 播放列表示例
主播放列表(master.m3u8
):
#EXTM3U
#EXT-X-VERSION:3
#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=2500000,RESOLUTION=1920x1080
high/index.m3u8
在主播放列表中,包含了多个不同质量的视频流(如低、中、高质量)。每个视频流有一个子播放列表文件(如 low/index.m3u8
,mid/index.m3u8
),该文件列出了具体的 .ts
文件。
子播放列表(low/index.m3u8
):
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
low/00001.ts
#EXTINF:10.0,
low/00002.ts
#EXTINF:10.0,
low/00003.ts
#EXT-X-ENDLIST
每个子播放列表列出了对应质量的视频分段,EXTINF
标签表示每个分段的时长。
3. HLS 工作流程
- 编码和分段:原始视频文件被编码为多个不同质量的流(比如 480p、720p、1080p),然后将每个流分割成小的
.ts
文件,每个.ts
文件通常是几秒钟的内容。 - 生成播放列表文件:主播放列表
.m3u8
文件会列出所有可用的流以及它们的码率和分辨率。每个流的播放列表会列出其对应的.ts
文件。 - 客户端请求:客户端请求
.m3u8
播放列表文件后,会根据当前网络状况选择合适的分辨率和码率,逐个请求对应的.ts
文件进行播放。 - 自适应流:客户端会根据带宽动态切换不同的
.ts
分段,保证视频播放的流畅性。例如,当网络带宽变差时,客户端会切换到低分辨率的视频流;带宽恢复时,客户端会切换回高分辨率流。
4. HLS 的优势
- 适应性强:HLS 支持根据客户端的带宽自动切换不同质量的视频流,保证了用户的观看体验。
- 广泛兼容:HLS 被许多设备和浏览器原生支持,包括 iOS 设备、Android 设备、Safari 浏览器等。
- 简单部署:HLS 使用普通的 HTTP 协议进行传输,无需额外的专用流媒体服务器。
- 支持直播:HLS 可以用于直播流传输,客户端可以实时获取最新的
.ts
文件进行播放。
5. 如何实现 HLS 流式传输
1. 编码和分段
首先,您需要将音视频文件进行编码,并分段。您可以使用工具如 FFmpeg 来执行此操作。
使用 FFmpeg 生成 HLS 流
假设您有一个名为 input.mp4
的视频文件,您想将其转换为 HLS 流并生成对应的 .m3u8
播放列表和 .ts
分段文件。
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls stream.m3u8
-i input.mp4
:输入视频文件。-profile:v baseline -level 3.0 -s 640x360
:设置视频编码器参数,指定分辨率。-hls_time 10
:每个.ts
文件的时长(单位:秒)。-hls_list_size 0
:生成无限制长度的播放列表,适合直播。-f hls
:指定输出格式为 HLS。
运行后,FFmpeg 会生成一个 stream.m3u8
播放列表文件以及多个 .ts
文件。
2. 部署 HLS 内容
将生成的 .m3u8
播放列表文件和 .ts
分段文件上传到 Web 服务器。您可以使用任何支持 HTTP 的服务器(如 Apache、Nginx 等)来提供这些文件。
配置服务器支持 .m3u8
和 .ts
文件的正确 MIME 类型:
.m3u8
:application/vnd.apple.mpegurl
.ts
:video/MP2T
在 Nginx 配置文件中添加如下内容:
server {
location /hls/ {
add_header Access-Control-Allow-Origin *;
add_header Content-Type application/vnd.apple.mpegurl;
add_header Cache-Control no-cache;
# 映射 HLS 播放列表和 ts 文件
root /path/to/hls/files;
}
}
3. 播放 HLS 流
前端使用 <video>
标签或 HLS 播放器来播放 .m3u8
文件。大多数现代浏览器(如 Safari、Chrome、Firefox 等)都支持 HLS 流媒体播放。您也可以使用像 Video.js、hls.js(基于 JavaScript)等播放器来播放 HLS 流。
使用 <video>
标签播放:
<video controls>
<source src="https://example.com/hls/stream.m3u8" type="application/x-mpegURL">
</video>
使用 HLS.js(适用于不支持 HLS 的浏览器):
<script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
<video id="video" controls></video>
<script>
var video = document.getElementById('video');
if(Hls.isSupported()) {
var hls = new Hls();
hls.loadSource('https://example.com/hls/stream.m3u8');
hls.attachMedia(video);
}
// HLS.js 不支持时使用 native HTML5 <video> 播放
else if (video.canPlayType('application/vnd.apple.mpegurl')) {
video.src = 'https://example.com/hls/stream.m3u8';
}
</script>
6. 总结
HLS 是一个强大的流媒体协议,适用于音视频文件的流式传输。它通过将音视频内容切割成多个小