摘要
M3U8 格式文件是一个纯文本文件,它是 HLS 协议规范的一部分,遵循 HLS 协议定义的在线多媒体播放列表(Playlist)规范。
1 M3U8 格式文件简介
M3U8 格式文件是一个纯文本文件,它是 HLS 协议规范的一部分,遵循 HLS 协议定义的在线多媒体播放列表(Playlist)规范。
HLS 全称是 HTTP Live Streaming,是一个由 Apple 公司提出的基于 HTTP 的媒体流传输协议,用于实时音视频流的传输。HLS 把整个流分成一个个小的基于 HTTP 的文件来下载,每次只下载一些。HLS 协议由三部分组成:HTTP、M3U8、TS。这三部分中,HTTP 是传输协议,M3U8 是索引文件,TS 是音视频的媒体信息。
2 M3U8 格式文件的构成
以下为一个 m3u8 格式文件内容的示例:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-KEY:METHOD=AES-128,URI="https://a.lzw.me/media/enkey?token=xxx" #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:10 #EXTINF:10.000, https://a.lzw.me/test/1.ts #EXTINF:10.000, https://a.lzw.me/test/2.ts #EXTINF:10.000, https://a.lzw.me/test/3.ts #EXTINF:9.720, https://a.lzw.me/test/4.ts #EXT-X-ENDLIST
在以上示例中包含了 m3u8 文件常见的字段。下面为一个M3U8文件可包含的基本字段及含义解释:
#EXTM3U:
M3U8文件头,必须在第一行。#EXT-X-VERSION:
指定 M3U8 版本号。#EXT-X-KEY:
若ts
视频片段进行了加密,则需配置该字段指定加密解析方式。例如在上面的示例中,该字段指定了加密算法为AES-128
,密钥通过请求https://a.lzw.me/media/enkey?token=xxx
获取,以用于解密后续下载的ts
文件。EXT-X-MEDIA-SEQUENCE:
第一个TS分片的序列号。对于视频点播资源该字段一般是 0,但是在直播场景下,这个序列号标识直播段的起始位置。#EXT-X-TARGETDURATION:
每个分片TS的最大的时长,单位为秒。#EXT-X-ALLOW-CACHE:
是否允许 cache,#EXT-X-ALLOW-CACHE:YES 、#EXT-X-ALLOW-CACHE:NO,默认情况下是YES。#EXTINF:extra info:
指定下一行的TS信息,如时长,带宽等。一般格式为#EXTINF:<duration>,[<title>]
, 后面可以继续跟其他的信息,逗号之前是当前分片的TS时长。分片时长要小于#EXT-X-TARGETDURATION
定义的值。#EXT-X-DISCONTINUITY:
该标签表明其前一个切片与下一个切片之间存在中断。#EXT-X-PLAYLIST-TYPE:
指定流媒体类型。#EXT-X-ENDLIST:
M3U8 文件结束符。
HLS 协议编码格式的基本要求主要包括:
- 视频编码格式为
H264
。 - 音频编码格式为
AAC
、MP3
或AC-3
。 - 音视频采用
ts
或mp4
格式,可包含多个多个视频片段。常见的主流方案多为ts
格式。 - 以
.m3u8
为后缀的播放列表文件,指定ts
文件索引等信息。
3 M3U8 格式文件的优点
做多码率的适配。HLS有一个特点:自适应码率流播(adaptive streaming)。M3U8 文件是一个纯文本的播放列表,其可配置多个不同码率的子 M3U8 文件入口地址。客户端可以根据网络状况自动选择不同码率的视频流,条件允许的情况下使用高码率,网络繁忙的时候使用低码率,并且自动在二者间随意切换。这对于流量敏感(流量付费)及网络状况较差的场景非常有利。
降低源服务器负载压力。M3U8的特点是将流媒体切分为若干 TS 片段,然后通过一个扩展的 m3u 列表文件将这些 TS 片段集中起来供客户端播放器接收。一旦切分完成,之后的分发过程完全不需要额外使用任何专门软件,普通的网络服务器即可,大大降低了 CDN 边缘服务器的配置要求,可以使用任何现成的CDN。分发使用的协议是最常见 HTTP,代理服务器对这个协议的缓存优化相当成熟,而很少有代理服务器对 RTSP 的进行缓存优化。
对于非实时视频,好处同样存在:播放使用HTTP协议的单个 MP4 格式的视频文件时,需要代理服务器支持 HTTP range request 以获取大文件中的一部分,但不是所有的代理服务器都对此有良好的支持。而 M3U 则只需要根据列表文件中的时间轴找出对应的 TS 片段下载即可,不需要 range request,对代理服务器的要求小很多。所有代理服务器都支持小文件的高效缓存。
为什么用 TS 而不是 MP4 格式。这是因为两个 TS 片段可以无缝拼接,播放器能连续播放,而 MP4 文件由于编码方式的原因,两段 MP4 不能无缝拼接,播放器连续播放两个 MP4 文件会出现破音和画面间断,影响用户体验。
4 获取在线视频网站播放的 M3U8 地址
m3u8
文件本质上是一个纯本文文件的播放列表,需要先以 http 协议从服务器上下载,因此我们可以从浏览器的网络请求列表中将它过滤出来。
在视频播放的页面,按 F12 打开浏览器开发者工具调试控制台,切换到网络(network)选项卡,然后在过滤框输入 .m3u8
关键字对请求资源进行过滤。接着刷新页面并播放视频,让页面资源重新请求,此时即可在过滤面板下看到该视频资源请求的 m3u8 的地址。参考如下图示例:
5 M3U8 加密与防盗链、防下载
常规的 m3u8 资源基本是以静态的 http 服务提供的,这让资源容易被盗用、被工具直接下载。为了对资源进行保护,常见 m3u8 的视频资源基本都会实现加密方案。
但对于如腾旭视频、优酷等大型的视频网站,为了避免收费视频资源被盗用播放、下载导出,其往往会生成时效非常短的 token 附加在 m3u8 地址、ts 分片地址等上面,作为服务器鉴权的依据。这种方案对于防盗链下载非常有效。
但是视频只要可以被播放,就避免不了泄露。最简单原始的方案,就是利用屏幕录像软件进行翻拍。但翻拍的缺点是其得到的内容无法于原始高清的视频相比。
当前各视频网站的无插件播放技术,基本都是基于 Media Source Extensions API 实现的。所以一种技术方案是利用浏览器的 MediaSource
对象接口,实现对网页媒体播放数据流的拦截,进而实现数据流拼接、转换和下载。浏览器油猴插件脚本 media-source-extract 即是该方案的一种实现。
影视资源采集站的目的是让其带有广告水印的视频尽可能广泛的分发传播,一般不会有任何的加密保护措施。
6 基于 HLS 协议的在线视频播放
在没有 HLS 协议支持的时代,基于流媒体的在线视频点播多采用 RTMP 协议和 Flash 服务等需 Native 插件支持的方案。
而在当前 Flash 早已被废弃,HLS 协议取而代之被广泛的应用于视频点播和直播领域。现在互联网上几乎所有的直播平台和在线视频播放网站,都是基于 HLS 协议实现的在线媒体视频播放功能。如腾讯视频、优酷、爱奇艺、广电电视台点播与直播,以及提供在线观看服务的各种电影网站等等。
由于 HLS 协议规范以 ts
或 mp4
音视频片段方式将完整的视频进行了分片,使得对视频进行快进、随意切换进度都非常简单,只需要根据 m3u8
配置的索引信息进行简单的定位计算即可实现。
支持 HLS 协议解析的媒体播放器,均可直接播放 .m3u8
格式的视频资源。在主流浏览器上(支持 Media Source Extensions API),基于 web 标准 API 即可以实现对 HLS 协议的支持,无需任何 Native 的播放器插件即可实现对 m3u8
格式文件的解析与视频播放。当前在浏览器上基于 HLS 的在线视频播放技术,基本都会采用开源库 hls.js 实现在线视频直播或点播方案。
以下为一个基于 hls.js
实现在线视频播放的 html
页面示例:
<!DOCTYPE html> <html lang="en"> <body> <video id="video"></video> <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script> <script> if (Hls.isSupported()) { var video = document.getElementById('video'); var hls = new Hls(); // bind them together hls.attachMedia(video); hls.on(Hls.Events.MEDIA_ATTACHED, function () { console.log('video and hls.js are now bound together !'); hls.loadSource('http://a.lzw.me/test/playlist.m3u8'); hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) { console.log( 'manifest loaded, found ' + data.levels.length + ' quality level' ); }); }); } </script> </body> </html>
可以看到,基于 hls.js
实现对 m3u8 资源的在线播放非常简单。
m3u8-player是一个较为完整的实现,可以支持对 m3u8 文件的播放,也可以支持直接复制 m3u8 文件的内容进行在线播放: