M3U8 视频文件

8,941 阅读19分钟

这篇文章只是 M3U、M3U8、HLS、TS 相关的一些基础概念

"M3U" 和 "M3U8" 文件都是苹果公司使用的 HTTP Live Streaming(HLS) 协议格式的基础,这种协议格式可以在 iPhone 和 Macbook 等设备播放。

HLS 解决方案

HLS(HTTP Live Streaming) 是由Apple公司定义的用于实时流传输的协议,HLS基于HTTP协议实现,传输内容包括两部分,一是M3U8描述文件,二是TS媒体文件。

1. HLS的优势为:自适应码率流播(adaptive streaming)。

效果就是客户端会根据网络状况自动选择不同码率的视频流,条件允许的情况下使用高码率,网络繁忙的时候使用低码率,并且能够自动在二者之间随意切换。这对移动设备网络状况不稳定的情况下保障流畅播放非常有帮助。实现方法是服务器端提供多码率视频流,并且在列表文件中注明,播放器根据播放进度和下载速度进行自动调整。

2. 为什么要用 TS 而不是 MP4

这是因为两个 TS 片段可以无缝拼接,播放器能连续播放,而 MP4 文件由于编码方式的原因,两段 MP4 不能无缝拼接,播放器连续播放两个 MP4 文件会出现破音和画面间断,影响用户体验。而且如果要在一段长达一小时的视频中跳转,如果使用单个 MP4 格式的视频文件,并且也是用 HTTP 协议,那么需要代理服务器支持 HTTP range request 获取大文件中的一部分。这样的话,对于代理服务器的性能来说要求较高。而 HTTP Live Streaming 则只需要根据列表文件中的时间轴找出对应的 TS 片段下载即可,不需要 range request,对代理服务器的要求小很多。所有代理服务器都支持小文件的高效缓存。

3. 可以使用FFmpeg转MP4为HLS(M3U8)文件。

4. hsl处理方案

核心,在于对于 m3u8 的文件解析和 通过 XHR 去完成对分片内容二进制文件的获取,然后使用 MSE 的 appendBuffer 去进行 buffer 的封装,然后自己完成合流的工作。

M3U8

M3U文件是记录了一个索引纯文本文件,可以指定一个或多个多媒体文件的位置,其文件扩展名是“M3U”或者“m3u”。打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放。M3U文件的作用通常是创建指向在线流媒体的播放列表,创建的文件可以轻松访问流媒体。

M3U8是Unicode版本的M3U,用UTF-8编码。

m3u8 文件实质是一个播放列表(playlist),其可能是一个媒体播放列表(Media Playlist),或者是一个主列表(Master Playlist)。

当 m3u8 文件作为媒体播放列表(Meida Playlist)时,其内部信息记录的是一系列媒体片段资源,顺序播放该片段资源,即可完整展示多媒体资源。对于点播来说,客户端只需按顺序下载片段资源,依次进行播放即可。而对于直播来说,客户端需要定时重新请求该 m3u8 文件,看下是否有新的片段数据需要进行下载并播放。

当 m3u8 作为主播放列表(Master Playlist)时,其内部提供的是同一份媒体资源的多份流列表资源(Variant Strean)。客户可以根据不同的网络状态选取合适码流的资源,并且最好根据用户喜好选择合适的资源内容。

m3u8 文件要么是媒体播放列表,要么是主播放列表。但无论是哪种列表,其有效组成均由两部分构成:

  • 以 #EXT 开头的为标签信息,作为对媒体资源的进一步描述;
  • 剩余的为资源信息,要么是片段资源(Media Playlist)路径,要么是 m3u8 资源(Master Playlist)路径;

m3u8文件遵循的条件:

  • m3u8 文件必须以 utf-8 进行编码,不能使用 Byte Order Mark(BOM)字节序, 不能包含 utf-8 控制字符(U+0000 ~ U_001F 和 U+007F ~ u+009F)。

  • 3u8 文件的每一行要么是一个 URI,要么是空行,要么就是以 # 开头的字符串。不能出现空白字符,除了显示声明的元素。

  • m3u8 文件中以 # 开头的字符串要么是注释,要么就是标签。标签以 #EXT 开头,大小写敏感。

m3u8 标签

标签用于指定 m3u8 文件的全局参数或在其后面的切片文件/媒体播放列表的一些信息。

#EXTM3U // 表明该文件是一个 m3u8 文件,必须在文件的第一行
#EXT-X-VERSION:3   //  HLS 的协议版本号
#EXT-X-ALLOW-CACHE:NO
#EXT-X-MEDIA-SEQUENCE:1572999465  // M3U8直播时的直播切换序列,当播放打开M3U8时,以这个标签的值作为参考,播放对应的序列号的切片
#EXT-X-TARGETDURATION:6 // 该标签指定了媒体文件持续时间的最大值,,播放文件列表中的媒体文件在EXTINF标签中定义的持续时间必须小于或者等于该标签指定的持续时间。该标签在播放列表文件中必须出现一次。
#EXT-QQHLS-PIC-WIDTH:0
#EXT-QQHLS-PIC-HEIGHT:0
#EXT-QQHLS-CK:CRC_16
#EXT-QQHLS-BN:8
#EXT-QQHLS-SEGMENT-TYPE:0
#EXT-QQHLS-SEGMENT_RANGE:1572999448-1572999472
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:11:57+08:00 // 片段取样时间
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006317
#EXT-SID:1572999465
#EXT-SC:SZ=254364&CK=e633
#EXT-BC:SZ=31744&CK=782e
#EXT-BC:SZ=31744&CK=256a
#EXT-BC:SZ=31744&CK=7b04
#EXT-BC:SZ=31744&CK=30dd
#EXT-BC:SZ=31744&CK=6d89
#EXT-BC:SZ=31744&CK=46d
#EXT-BC:SZ=31744&CK=8f4
#EXT-BC:SZ=32156&CK=71b5
#EXTINF:5.000,
100204101-1572999465.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
// EXTINF为M3U8列表中每一个分片的duration,描述信息
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:02+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006322
#EXT-SID:1572999466
#EXT-SC:SZ=287264&CK=6abc
#EXT-BC:SZ=35840&CK=aa34
#EXT-BC:SZ=35840&CK=42f1
#EXT-BC:SZ=35840&CK=46f
#EXT-BC:SZ=35840&CK=3fd
#EXT-BC:SZ=35840&CK=75b2
#EXT-BC:SZ=35840&CK=af4f
#EXT-BC:SZ=35840&CK=52a1
#EXT-BC:SZ=36384&CK=86ed
#EXTINF:5.000,
100204101-1572999466.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:07+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006327
#EXT-SID:1572999467
#EXT-SC:SZ=289708&CK=749f
#EXT-BC:SZ=35840&CK=a209
#EXT-BC:SZ=35840&CK=abb9
#EXT-BC:SZ=35840&CK=13ab
#EXT-BC:SZ=35840&CK=40b7
#EXT-BC:SZ=35840&CK=2e10
#EXT-BC:SZ=35840&CK=3a00
#EXT-BC:SZ=35840&CK=62ae
#EXT-BC:SZ=38828&CK=65e5
#EXTINF:5.000,
100204101-1572999467.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:11+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006331
#EXT-SID:1572999468
#EXT-SC:SZ=523016&CK=97c
#EXT-BC:SZ=64512&CK=a072
#EXT-BC:SZ=64512&CK=b80e
#EXT-BC:SZ=64512&CK=13ee
#EXT-BC:SZ=64512&CK=2c70
#EXT-BC:SZ=64512&CK=992c
#EXT-BC:SZ=64512&CK=3c51
#EXT-BC:SZ=64512&CK=a079
#EXT-BC:SZ=71432&CK=a66
#EXTINF:5.000,
100204101-1572999468.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:16+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006336
#EXT-SID:1572999469
#EXT-SC:SZ=670032&CK=6479
#EXT-BC:SZ=82944&CK=dc72
#EXT-BC:SZ=82944&CK=e970
#EXT-BC:SZ=82944&CK=4ca4
#EXT-BC:SZ=82944&CK=3d1b
#EXT-BC:SZ=82944&CK=fa9b
#EXT-BC:SZ=82944&CK=e9d3
#EXT-BC:SZ=82944&CK=ee0b
#EXT-BC:SZ=89424&CK=b998
#EXTINF:5.000,
100204101-1572999469.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:21+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006341
#EXT-SID:1572999470
#EXT-SC:SZ=777756&CK=a13c
#EXT-BC:SZ=96256&CK=e95e
#EXT-BC:SZ=96256&CK=f459
#EXT-BC:SZ=96256&CK=33a6
#EXT-BC:SZ=96256&CK=bb7c
#EXT-BC:SZ=96256&CK=f3e4
#EXT-BC:SZ=96256&CK=635d
#EXT-BC:SZ=96256&CK=67e9
#EXT-BC:SZ=103964&CK=b938
#EXTINF:5.000,
100204101-1572999470.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:27+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006347
#EXT-SID:1572999471
#EXT-SC:SZ=479212&CK=c493
#EXT-BC:SZ=59392&CK=dec8
#EXT-BC:SZ=59392&CK=1ee8
#EXT-BC:SZ=59392&CK=b9bf
#EXT-BC:SZ=59392&CK=8b9c
#EXT-BC:SZ=59392&CK=29fe
#EXT-BC:SZ=59392&CK=493
#EXT-BC:SZ=59392&CK=ae5f
#EXT-BC:SZ=63468&CK=630
#EXTINF:5.000,
100204101-1572999471.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA
#EXT-X-PROGRAM-DATE-TIME:2019-11-06T10:12:32+08:00
#EXT-QQHLS-MACHINEID:56448
#EXT-QQHLS-START-TIME:1573006352
#EXT-SID:1572999472
#EXT-SC:SZ=266396&CK=648
#EXT-BC:SZ=32768&CK=a085
#EXT-BC:SZ=32768&CK=8233
#EXT-BC:SZ=32768&CK=1831
#EXT-BC:SZ=32768&CK=4042
#EXT-BC:SZ=32768&CK=f0eb
#EXT-BC:SZ=32768&CK=cd3a
#EXT-BC:SZ=32768&CK=e245
#EXT-BC:SZ=37020&CK=f6e3
#EXTINF:5.000,
100204101-1572999472.ts?cdncode=/18907E7BE0798990/&HLSP2P=1&buname=qqlive&sdtfrom=10002212&vkey=F1FE87B5E6D84B6FEFBB683D7C2558C08C8CF7B6E752E05C689F1117D651C359E4C7460F44AF4CA4D54188D17A34DB8F3D1E1A9B03F5F5509AFFC93EEA5B90B835EB1E096C8EA81447313AD2761912137D4F692E8AEC2D52E0E3ACD02E09272F82A1FC8573388BDE57FBE56A424E01BA

其他的一些常用标签:

  • EXT-X-DISCONTINUITY 该标签表明其前一个切片与下一个切片之间存在中断。EXT-X-DISCONTINUITY 的一个经典使用场景就是在视屏流中插入广告,由于视屏流与广告视屏流不是同一份资源,因此在这两种流切换时使用 EXT-X-DISCONTINUITY 进行指明,客户端看到该标签后,就会处理这种切换中断问题,让体验更佳。

  • EXT-X-KEY 媒体片段可以进行加密,而该标签可以指定解密方法。

  • EXT-X-PLAYLIST-TYPE:表明流媒体类型。全局生效。该标签为可选标签。 可选值如下:

    • VOD 即 Video on Demand,表示该视屏流为点播源,因此服务器不能更改该 m3u8 文件;
    • EVENT 表示该视频流为直播源,因此服务器不能更改或删除该文件任意部分内容(但是可以在文件末尾添加新内容)

注:VOD 文件通常带有 EXT-X-ENDLIST 标签,因为其为点播源,不会改变;而 EVEVT 文件初始化时一般不会有 EXT-X-ENDLIST 标签,暗示有新的文件会添加到播放列表末尾,因此也需要客户端定时获取该 m3u8 文件,以获取新的媒体片段资源,直到访问到 EXT-X-ENDLIST 标签才停止。

  • EXT-X-PROGRAM-DATE-TIME 该标签使用一个绝对日期/时间表明第一个样本片段的取样时间。

  • EXT-X-MEDIA-SEQUENCE:表示播放列表第一个 URL 片段文件的序列号,每个媒体片段 URL 都拥有一个唯一的整型序列号。 每个媒体片段序列号按出现顺序依次加 1。媒体片段序列号与片段文件名无关。如果该标签未指定,则默认序列号从 0 开始。

  • EXT-X-ENDLIST 若出现EXT-X-ENDLIST标签,则表明M3U8文件不会再产生更多的切片,可以理解为该M3U8已停止更新,并且播放分片到这个标签后结束。M3U8不仅仅是可以作为直播,也可以作为点播存在,在M3U8文件中保存所有切片信息最后使用EXT-X-ENDLIST结尾,这个M3U8即为点播M3U8。EXT-X-ENDLIST标签可能会出现在播放列表文件的任何地方,但是不能出现两次或以上。

  • EXT-X-STREAM-INF EXT-X-STREAM-INF标签出现在M3U8时,主要是出现在多级M3U8文件中时,例如M3U8中包含子M3U8列表,或者主M3U8中包含多码率M3U8时;该标签后需要跟一些属性,下面就来逐一说明一下这些属性:

    • BANDWIDTHBANDWIDTH的值为最高码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的最大码率(必要参数)。
    • AVERAGE-BANDWIDTHAVERAGE-BANDWIDTH的值为平均码率值,当播放EXT-X-STREAM-INF下对应的M3U8时占用的平均码率(可选参数)。
    • CODECS:CODECS的值用于声明EXT-X-STREAM-INF下面对应M3U8里面的音视频编码、视频编码的信息(可选参数)。
    • RESOLUTION:M3U8中视频的宽高信息描述(可选参数)。
    • FRAME-RATE:子M3U8中的视频帧率(可选参数)。

客户端播放M3U8的一些标准:

  1. 分片必须是动态改变的,序列不能相同,并且序列必须是增序的
  2. 当M3U8没有出现EXT-X-ENDLIST标签时,无论这个M3U8列表中有多少个分片,播放分片都是从倒数第三片开始播放,如果不满3片则不应该播放。当然如果有些播放器做了特别定制了,则可以不遵照这个原则。
  3. 以播放当前分片的duration时间刷新M3U8列表,然后做对应的加载动作。
  4. 如果播放列表在刷新之后与之前的列表相同,那么在播放当前分片duration一半的时间内在刷新一次。
  5. 前一片分片和后一片分片有不连续的时候,播放可能会出错,那么需要X-DISCONTINUTY标签来解决这个错误。

注意事项

  • 有两种请求 m3u8 播放列表的方法:一是通过 m3u8 的 URI 进行请求,则该文件必须以 .m3u8.m3u 结尾;二是通过 HTTP 进行请求,则请求头 Content-Type 必须设置为 application/vnd.apple.mpegurl 或者 audio/mpegurl

  • 空行和注释行在解析时都忽略。

  • 媒体播放列表(Media Playlist)的流资源总时长就是各切片资源的时长之和。

TS文件

TS(Transport Stream)是一种音视频封装格式,全称MPEG2-TS。MPEG-TS主要应用于实时传送的节目,比如实时广播的电视节目。

TS文件(流)可以分为三层:TS层(Transport Stream)、PES层(Packet Elemental Stream)、ES层(Elementary Stream)。

ES层就是音视频数据,PES层是在音视频数据上加了时间戳等对数据帧的说明信息,TS层是在PES层上加入了数据流识别和传输的必要信息。TS文件(码流)由多个TS Packet组成的。

TS文件(码流)的分层结构图

TS文件(码流)的分层结构图

TS流生成流程

  1. 将原始音视频数据压缩之后,压缩结果组成一个基本码流(ES)。
  2. 对ES(基本码流)进行打包形成PES。
  3. 在PES包中加入时间戳信息(PTS/DTS)。
  4. 将PES包内容分配到一系列固定长度的传输包(TS Packet)中。
  5. 在传输包中加入定时信息(PCR)。
  6. 在传输包中加入节目专用信息(PSI) 。
  7. 连续输出传输包形成具有恒定比特率的MPEG-TS流。

TS流解析流程

  1. 复用的MPEG-TS流中解析出TS包;
  2. 从TS包中获取PAT及对应的PMT;
  3. 从而获取特定节目的音视频PID;
  4. 通过PID筛选出特定音视频相关的TS包,并解析出PES;
  5. 从PES中读取到PTS/DTS,并从PES中解析出基本码流ES;
  6. 将ES交给解码器,获得压缩前的原始音视频数据。

ts文件合并

加密后的ts文件不能直接合并或播放,需要使用key对每个ts文件解密。

具体参见 加密的m3u8、ts文件合并-作者:骏马金龙

参考资料: