一、概述
????????HLS(HTTP Live Streaming) 是苹果公司基于HTTP提出来的一种自适应码率 的流媒体传输协议,编号RFC8216 ,苹果公司为HLS建立的官网是:HTTP Live Streaming (HLS) - Apple Developer ,有需求的同学可以在其官网了解HLS的使用方法、功能扩展、性能优化等相关信息。HLS主要内容由HTTP + M3U8 + TS这三个部分共同组成,其中HTTP 是最常见的应用层协议了,我们日常基本的浏览器上网就是基于HTTP协议;而TS是音视频编码标准MPEG-2中定义的一种媒体流封装复用格式,TS相关的详情可以参考我的上一篇文章《MPEG-2 TS流结构浅析 》;既然HTTP和TS都是其他协议或标准中规定的内容,那么HLS的核心就只能是这个M3U8了。
直播模型架构全链路
在实际应用场景中,M3U8是以文件的形式出现,即xxx.m3u8或xxx.m3u这种文件格式。以如上图所示的直播模型架构链路图为例:
采集端将采集到的音视频媒体数据经过编码压缩、文件封装后,一般采用时延更低的RTMP协议推流到业务服务器; 业务服务器从RTMP提取到数据流后,为了适应播放端采用的HLS拉流协议,会将数据流分割成一个一个很小TS分片(一般每个分片在10秒左右); 播放端要播放某个直播内容时,服务器会先下发一个一级M3U8文件给客户端,这个一级M3U8文件中根据不同的网络环境(带宽),提供了不同码率的媒体流地址; 播放端选择并请求某个码率的媒体流地址后,服务器会下发一个二级M3U8文件,该文件中按顺序列出了一个个TS分片的下载地址; 播放端解析这个M3U8文件后,将这一个个TS分片下载下来,然后将它们拼接、解封装、解码,最终完成播放;
与其他的流媒体传输协议相比,HLS存在如下优势:
对比RTMP协议,HLS播放端不依赖指定插件,只需支持HTTP即可; 对比RTP协议,HLS协议的网络兼容性好,其基于HTTP的数据包可以方便地通过防火墙或者代理服务器,且容易使用内容分发网络CDN来完成数据流高效传输; 其自适应码率的特性,使其可以应用在不同的网络环境,提高观感体验;
劣势:
从本质上来说,HLS是以微观的点播实现宏观的直播,相比其他实时流形式的传输协议,其存在较高的时延;
二、M3U8
? ? ? ? M3U8文件中的内容主要由标签(TAG) 、属性列表(Attribute Lists) 、播放地址(URI) 构成。
????????其中播放地址是比较简单的,其一般单独占用一行。该地址一般由.m3u8、.m3u、.ts结尾(实际应用中这些后缀后面还可能会带着由问号(?)分割的其他应用参数),前两种结尾的播放地址代表当前是一个一级M3U8文件,这些地址指向的是一个个二级M3U8文件;而以.ts结尾的播放地址代表当前是一个二级M3U8文件,这些地址指向的是一个个具体的ts分片下载地址。
????????实际应用中访问或请求M3U8文件的方式有两种,一种是直接请求.m3u8或.m3u结尾的路径地址,另一种则是需要设置HTTP的Content-Type字段值为"application/vnd.apple.mpegurl" 或?"audio/mpegurl"。
2.1、属性列表
? ? ? ? 在一些标签后面跟随的是属性列表,属性列表是用逗号分割开来的键值对列表。如下面的语法格式所示,属性列表中的属性名、'='、属性值之间不能有空格,属性名可以是由数字[0,9]、大写字母[A,Z]、和'-'这些字符构成。
属性名=属性值
????????属性值的取值类型如下:
decimal-integer,十进制整数:由数字[0,9]组成的不带引号的数字串表示一个十进制整数,该数字串长度不能超过20位,取值则位于0到2^64-1之间; hexadecimal-sequence,十六进制序列:由 数字[0,9]、大写字母[A,F]、且前缀为 0x 或 0X 组合成的不带引号的字符串序列,其长度取决于前面的属性名; decimal-floating-point,无符号十进制浮点数:由数字[0,9]和小数点'.'组成的不带引号的数字串表示一个非负十进制浮点数; signed-decimal-floating-point,有符号十进制浮点数:由数字[0,9]、负号'-'、和小数点'.'组成的不带引号的数字串表示一个十进制浮点数; quoted-string,带引号字符串:携带一对双引号的字符串,双引号之间不能再出现回车符、换行符、双引号; enumerated-string,枚举字符串:由属性名显式定义的一个不带引号的字符串,该类型中不能出现双引号、逗号、和空格; decimal-resolution,十进制分辨率:由字符'x'分割的两个十进制整数,第一个整数表示水平像素尺寸,第二个整数表示垂直像素尺寸;
2.2、标签
? ? ? ? 在M3U8文件中,标签以#号开头,形如#EXTM3U。根据HLS文档的中定义,标签有如下四种分类:
Basic Tags,基本标签: 该类标签必须出现在每个M3U8文件中;Media Segment Tags,媒体片段标签: 该类标签和其跟随的URI一起指定一个媒体片段。有些媒体片段标签仅作用于其下一行的片段,而其他的媒体片段标签作用于所有子序列片段,直到另外一个相同标签实例出现。一个媒体片段标签一定不能出现在主播放列表中;Media Playlist Tags,媒体播放列表标签: 该类标签是描述媒体播放列表的全局参数。一个媒体播放列表中,每种类型的媒体播放列表标签只能出现一次。媒体播放列表标签不能出现在主播放列表中;Master Playlist Tags,主播放列表标签: 主播放标签定义了Variant Stream、Rendition和其他显示的全局参数,主播放列表标签不能出现在媒体播放列表中;
????????其中的媒体片段(Media Segment)可以理解为一个TS分片;主播放列表(Master Playlist)可以理解为一级M3U8;媒体播放列表(Media Playlist)可以理解为二级M3U8;Variant Stream可翻译理解为可变流,其是针对不同的网络环境(带宽),提供的不同码率的媒体源;Rendition可翻译理解为译本(翻译的版本),其可以是对同一段视频提供的不同语种的音频或字幕,或者同一段视频不同拍摄视角的显示形式;
标签类型
标签 ????????说明 基本标签 EXTM3U ????????标识当前是一个M3U8文件,该标签必须出现在文件的第一行; EXT-X-VERSION ????????标识HLS的协议版本号,该标签作用于整个M3U8文件,且每个M3U8文件中该标签只等出现一次。
????????该标签出现的格式形如:#EXT-X-VERSION:<n>,其中n代表版本号;
媒体片段标签 EXTINF ? ? ? ? 该标签用于指定一个TS分片的时长,而且对于每一个TS分片该标签都是必须的。该标签格式形如:#EXTINF:<duration>,[<title>],其中的title作为当前TS分片的标题是一个UTF-8文本;
????????其中的duration应该是以秒为单位的浮点数或整数,为了避免大量TS分片累积出现时长不准确,duration应尽可能取浮点数,但是如果当前HLS使用的协议版本小于3,那该值必须四舍五入以取整数;
EXT-X-BYTERANGE ????????该标签表明当前TS分片是当前播放列表中、该标签下一行的播放地址URI指定资源的一个子范围,没有该标签时,表示当前TS分片就是整个URI资源。使用该标签需要版本号大于或等于4;
????????该标签格式形如:#EXT-X-BYTERANGE:<n>[@<o>],其中整数n代表该子范围的字节长度;o则是一个整数类型的可选项,当指定o时,o代表该子范围的起始位置在整个资源字节长度中的偏移量;未指定时,o的值就是上一个TS分片末尾的下一个字节的偏移量,此时的上一个TS分片必须是同一个URI指定的相同资源;
EXT-X-DISCONTINUITY ? ? ? ? 该标签出现时,表示当前TS分片和前一个TS分片是不连续的,该标签格式形如:#EXT-X-DISCONTINUITY;
? ? ? ? 当这些内容发生变化时,该标签必须出现:1、文件格式;2、编号、类型、跟踪标识;3、时间戳序列;4、编码参数;5、编码序列;? ??
EXT-X-KEY ? ? ? ? 该标签指定TS分片的加密方式,该标签作用于播放列表文件中携带相同KEYFORMAT属性的、当前和下一个EXT-X-KEY标签之间的EXT-X-MAP标签声明的、每个媒体分片和媒体初始化部分,如果拥有不同KEYFORMAT属性的EXT-X-KEY标签最终产生的密钥相同,那么这些标签可以应用于同一个媒体片段;
? ? ? ? 该标签格式形如:#EXT-X-KEY:<attribute-list>,其中的属性列表包含如下几个属性:
? ? ? ? 1、METHOD:该属性是必须的,其属性值用枚举字符串表示加密算法,其可以取NONE(未加密)、AES-128、SAMPLE-AES这三个值;
? ? ? ? 2、URI:用一个带引号的字符串表示获取密钥的URI,除了未加密的情况外,该属性是必须的;
? ? ? ? 3、IV:该属性值是一个16进制序列,指定了一个128位无符号整数的初始化向量,用于密钥,使用该属性需要协议版本号大于或等于2;
? ? ? ? 4、KEYFORMAT:该可选属性的值是一个带引号的字符串,它指定了URI所标识的资源中的密钥格式,使用该属性需要协议版本号大于或等于5;
? ? ? ? 5、KEYFORMATVERSIONS:该可选属性值是一个带引号的字符串,包含一个或多个正整数,用“/”字符分隔(例如,“1”,“1/2”或“1/2/3”)。该属性未指定时,默认KEYFORMAT的版本为1;该属性指定时,如果定义了一个特定KEYFORMAT的多个版本,这个属性可以用来指示这个实例遵从的一个或多个版本;
EXT-X-MAP ? ? ? ? 该标签指定了如何获取媒体初始化部分来解析适用的媒体片段,它适用于播放列表中出现在它后面的每一个媒体片段,直到下一个EXT-X-MAP标签或直到播放列表结束;
? ? ? ? 当播放列表中的的第一个媒体片段没有紧跟着媒体初始化部分出现,那么应该提供一个EXT-X-MAP标签给这个携带EXT-X-I-FRAMES-ONLY标签的播放列表;在包含EXT- X-I-FRAMES-ONLY标签的媒体播放列表中使用EXT-X-MAP标签需要版本号大于等于5,在不包含EXT- X-I-FRAMES-ONLY标签的媒体播放列表中使用EXT-X-MAP标签需要版本号大于等于6;
? ? ? ? EXT-X-MAP标签格式形如:#EXT-X-MAP:<attribute-list>,其中的属性列表包含如下几个属性:
? ? ? ? 1、URI:该属性是必须的,其值是一个带引号的字符串,表示包含媒体初始化部分的资源;
? ? ? ? 2、BYTERANGE:该属性是可选的,如果不存在,则字节范围是由URI指示的整个资源;如果存在,该属性值是一个带引号的字符串,表示URI属性标识的资源的字节范围,这个范围应该只包含媒体初始化部分;
EXT-X-PROGRAM-DATE-TIME ? ? ? ? 该标签标签使用一个绝对日期和/或时间表明第一个样本片段的取样时间,其格式形如:#EXT-X-PROGRAM-DATE-TIME:<date-time-msec>,其中date-time-msec是一个?ISO/IEC 8601:2004 规定的日期格式,形如:YYYY-MM-DDThh:mm:ss.SSSZ;
? ? ? ? 例如:#EXT-X-PROGRAM-DATE-TIME:2010-02-19T14:54:23.031+08:00
EXT-X-DATERANGE ????????该标签格式形如:#EXT-X-DATERANGE:<attribute-list>,其表示了一系列由属性键值对组成的日期范围,其中的attribute-list包含如下几个属性:
? ? ? ? 1、ID:该属性是必须的,带双引号的字符串表示时间范围标识;
? ? ? ? 2、CLASS:该可选属性是由客户端定义的带引号的字符串,指定一组属性及其关联的值语义,所有具有相同CLASS属性值的Date range必须遵守这些语义;
? ? ? ? 3、START-DATE:该必选属性指定日期范围的起始位置;
? ? ? ? 4、END-DATE:该可选属性指定日期范围的结束位置,该结束时间应该大于等于起始时间;
? ? ? ? 5、DURATION:该非负浮点型、可选属性值表示时间范围的持续时间;
? ? ? ? 6、PLANNED-DURATION:可选的、以秒为单位的、非负浮点数表示日期范围的预期持续时间寿命;
? ? ? ? 7、X-<client-attribute>:该属性可选,'X-'前缀定义了一个为客户端定义的属性保留的名称空间,其中的client-attribute需要满足上面2.1小节对属性名的规范,客户端定义自己的属性名时应该使用反向DNS语法,以避免冲突;属性值必须是引号字符串、十六进制序列或浮点小数;例如:X-COM-EXAMPLE- AD-ID="XYZ123"
? ? ? ? 8、SCTE35-CMD、SCTE35-OUT、SCTE35-IN:用于携带SCTE-35数据;
? ? ? ? 9、END-ON-NEXT:该属性是可选的,取值为枚举字符串,只能取YES;该属性表示当前时间范围的末尾,它也等于下一个时间范围的START-DATE,下一个时间范围是指具有相同CLASS属性值的、带有START-DATE属性的、最早的一个时间范围;
? ? ? ? 如果当前标签携带了END-ON-NEXT=YES属性对,那么就不能携带DURATION或END-DATE属性,但必须携带CLASS属性,其他携带相同CLASS属性的EXT-X-DATERANGE标签的时间范围不能重叠;
? ? ? ? 如果一个时间范围既没有DURATION属性、END-DATE,也没有END-ON- NEXT=YES属性,那么该时间范围的持续时间是未知的,即使它携带了PLANNED- DURATION属性;如果时间范围同时包含DURATION和END-DATE属性,那么END-DATE属性的值必须等于START-DATE+DURATION;
? ? ? ? 如果一个播放列表包含一个EXT-X-DATERANGE标签,那么它也必须至少包含一个EXT-X-PROGRAM-DATE-TIME标签;如果一个播放列表包含两个具有相同ID属性值的EXT-X-DATERANGE标签,那么两个标签中出现的任何属性名必须具有相同的属性值;
媒体播放列表标签 EXT-X-TARGETDURATION ? ? ? ? 该标签是必选的,适用于整个播放列表,其指定了当前播放列表中最大的媒体片段时长。当播放列表中EXTINF标签指定的时长四舍五入后,必须小于该目标时长(Target Duration),过长的片段会触发播放停顿或其他错误;
? ? ? ? 该标签形如:#EXT-X-TARGETDURATION:<s>,其中s是以秒为单位的十进制整数表示时长;
EXT-X-MEDIA-SEQUENCE ? ? ? ? 该标签表示播放列表文件中出现的第一个媒体片段的媒体序列号,形如#EXT-X-MEDIA-SEQUENCE:<number>,其中number是一个十进制整数表示序列号;
????????如果媒体播放列表文件不包含EXT-X-MEDIA-SEQUENCE标签,那么媒体播放列表中第一个媒体片段的媒体序列号将被认为是0;如果包含,那么该标签必须出现在播放列表的第一个媒体分片之前;客户端解析M3U8时不能认为不同媒体播放列表中、具有相同媒体序列号的片段是相互匹配的;
EXT-X-DISCONTINUITY-SEQUENCE ? ? ? ? 该标签允许在相同变体(Variant)流的不同译本(Rendition)之间进行同步,或者在媒体播放列表中具有EXT-X-DISCONTINUITY标签的不同变体流之间进行同步;该标签格式形如:#EXT-X-DISCONTINUITY-SEQUENCE:<number>,其中number是整数;
? ? ? ? 如果播放列表中不包含当前标签,那么播放列表中的第一个媒体片段的不连续序列号将被认定为0;该标签必须出现在播放列表的第一个媒体片段前,也必须出现在任何EXT-X-DISCONTINUITY标签前;
EXT-X-ENDLIST ? ? ? ? ?该标签可能出现在媒体播放列表文件的任何地方,表示不会再有媒体片段被添加到当前媒体列表文件中了,该标签格式形如:#EXT-X-ENDLIST; EXT-X-PLAYLIST-TYPE ? ? ? ? 该可选标签作用于整个媒体播放列表文件,其提供了媒体播放列表的可变性信息,该标签格式形如:#EXT-X-PLAYLIST-TYPE:<type-enum>,其中的ype-enum取EVENT或VOD;
? ? ? ? 如果type-enum取EVENT代表直播,媒体片段只能被添加到媒体播放列表的末尾;如果取VOD(Video On Demand,视频点播),那么这个媒体播放列表是不能更改的;
EXT-X-I-FRAMES-ONLY ? ? ? ? 该标签表示当前播放列表中的每个媒体片段都描述了一个单独的I帧,I帧是编码后的、不依赖其他帧的视频帧,I帧播放列表可用于trick,比如快进、快退;该标签作用于整个播放列表,其格式形如:#EXT-X-I-FRAMES-ONLY,使用该标签需要版本号大于或等于4;
? ? ? ? 播放列表中携带该标签的媒体片段时长,等于当前I帧的显示时间到下一个I帧的显示时间 之间的时间段,如果当前I帧是最后一个,则该时长等于I帧显示时间到最后末尾的显示时间;
? ? ? ? 包含该标签的媒体资源必须以媒体初始化部分开始,或者伴随着一个EXT-X-MAP标签来指示媒体初始化部分,这样客户端可以按任意顺序加载和解码I帧片段,如果I帧片段携带EXT-X-BYTERANGE标签,那么就不能再出现媒体初始化部分;客户端可以认为媒体初始化部分是由EXT-X-MAP标签定义,或者位于资源的起始到第一个I帧片段的偏移位置;
主播放列表标签 EXT-X-MEDIA ? ? ? ? 该标签用于关联包含相同内容的可选译本的媒体播放列表,例如可以使用三个EXT-X-MEDIA标签来表示同一段视频的英语、法语、西班牙语版本的纯音频播放列表,或者可以使用两个EXT-X-MEDIA标签来表示显示两个不同视角的纯视频媒体播放列表;
? ? ? ? 该标签格式形如:#EXT-X-MEDIA:<attribute-list>,其中的属性列表可取如下内容:
? ? ? ? 1、TYPE:该必选属性的值是枚举字符串,可以取值:AUDIO、VIDEO、SUBTITLES、CLOSED-CAPTIONS;通常,关闭标题的媒体在视频流中携带,因此带有CLOSED- CAPTIONS类型的EXT-X-MEDIA标签不指定译本,CLOSED- CAPTION类型的媒体出现在每个视频译本的媒体片段中;
? ? ? ? 2、URI:该可选属性值是带引号的字符串,其指定了一个媒体播放列表文件;如果TYPE属性取值为CLOSED-CAPTIONS,那么该属性就不能出现;
? ? ? ? 3、GROUP-ID:该必选属性值是带引号的字符串,其指定了属于哪个译本分组;
? ? ? ? 4、LANGUAGE:该可选属性值是带引号的字符串,其指定在译本中使用的主要语言;
? ? ? ? 5、ASSOC-LANGUAGE:该可选属性值是带引号的字符串,与LANGUAGE属性相比,扮演的是不同的角色,比如书面语言与口语;
? ? ? ? 6、NAME:该必选属性值是带引号的字符串,是对当前译本的描述;
? ? ? ? 7、DEFAULT:该可选属性值是一个枚举字符串,取值有YES和NO,默认取NO。如果该属性值取YES,那么客户端应该在没有用户指示不同选择信息的情况下播放当前译本;
? ? ? ? 8、AUTOSELECT:该可选属性值是一个枚举字符串,取值有YES和NO,默认取NO。如果该属性值取YES,那么客户端可能会在没有明确用户偏好的情况下选择播放这个译本,因为它匹配当前的播放环境,比如选择的系统语言;如果当前译本的DEFAULT属性值取YES,那么AUTOSELECT属性出现时也应该取值YES;
? ? ? ? 9、FORCED:只有TYPE属性是SUBTITLES时,FORCED属性才会出现。该可选属性值是一个枚举字符串,取值有YES和NO,默认取NO。取NO时表示译本包含响应明确的用户请求而播放的内容;取YES时,表示译本包含被认为是播放所必需的内容,当选择FORCED译本时,客户端应该选择与当前播放环境(例如语言)最匹配的一个;
? ? ? ? 10、INSTREAM-ID:该属性值是一个带引号的字符串,用于指定媒体播放列表中的片段的译本。如果TYPE属性值是CLOSED-CAPTIONS,那么当前属性是必须的,在这种情况下,它必须有一个值:"CC1", "CC2", "CC3", "CC4",或"SERVICEn",其中n必须是1到63之间的整数(例如,"SERVICE3"或"SERVICE42"),“CC1”、“CC2”、“CC3”和“CC4”表示第21行数据服务通道,?“SERVICE”值表示数字电视封闭字幕服务块号码;如果TYPE属性取其他值,则不能出现当前属性;
? ? ? ? 11、CHARACTERISTICS:该可选属性值是一个用逗号分割的、带引号的字符串,包含一个或多个统一类型标识符UTI,每个UTI都表明了译本的个体特征。字幕译本可能包含这些字符串:"public.accessibility.transcribes-spoken-dialog","public.accessibility.describes-music-and-sound","public.easy-to-read";音频译本可能包含这些:"public.accessibility.describes-video";
? ? ? ? 12、CHANNELS:该属性值是一个带引号的字符串,指定了一个有序的、反斜杠分隔的("/")参数列表。如果TYPE属性是AUDIO,那么第一个参数是表示为十进制整数的音频通道计数,表示在译本的任何媒体片段中出现的独立、同时的音频通道的最大数量。例如,AC-3 译本会有一个CHANNELS=“6”的属性。所有音频EXT-X-MEDIA标签都应该有一个CHANNELS属性,如果一个主播放列表包含两个用相同编解码器编码但不同数量的通道,那么CHANNELS属性是必需的;?否则,是可选的;
? ? ? ? 具有相同GROUP-ID和TYPE属性值的一个或多个EXT-X-MEDIA标签定义了一个译本组,组内的每个成员必须是相同内容的替代版本;
? ? ? ? 一个播放列表中所有EXT-X-MEDIA标签遵循这些约束:1、同一组中的所有EXT-X-MEDIA标签必须有不同的NAME属性;2、同一组中DEFAULT属性值是YES的EXT-X-MEDIA标签最多只能有一个;3、每个带有AUTOSELECT=YES属性的EXT-X-MEDIA标签应该包含与该组中其他AUTOSELECT=NO标签不同的属性:LANGUAGE、ASSOC-LANGUAGE、FORCED和CHARACTERISTICS属性;
EXT-X-STREAM-INF ? ? ? ? 该标签指定了一个可变流(Variant Stream),其后面必须跟随指定一个携带可变流译本的媒体播放列表的URI行。该标签格式形如:、
????????#EXT-X-STREAM-INF:<attribute-list>
? ? ? ? <URI>
? ? ? ? 其中的属性列表用于描述不同变体流的信息,该标签包含如下属性:
? ? ? ? 1、BANDWIDTH:每个EXT-X-STREAM-INF标签都必须包含BANDWIDTH属性,该属性值是一个单位是bps(bits per second)的十进制整数,其表示当前可变流的最高比特率;如果一个可变流中的所有媒体片段已经被创建,那么当前属性值必须是由所有可播放的译本组合产生的最大的峰值段比特率的和;如果在显示内容所有媒体片段编码之前,主播放列表是可用的,那么当前属性值应该取相同编码类型的、类似内容的、代表性时段的带宽值;
? ? ? ? 2、AVERAGE-BANDWIDTH:该属性可选,类似BANDWIDTH属性,但其代表的是平均带宽;
? ? ? ? 3、CODECS:每个EXT-X-STREAM-INF标签都应该包含这个属性,其取值为用逗号分隔开的带引号字符串,用于指示当前变体流中的编码格式或文件封装格式;
? ? ? ? 4、RESOLUTION:该可选属性用decimal-resolution类型描述当前可变流的最佳图像分辨率,如果当前可变流中包含视频,则建议选用该属性。
? ? ? ? 5、FRAME-RATE:该属性值是四舍五入到小数点后三位的浮点数,表示可变流中所有视频的最大帧率;该属性是可选的,但如果可变流中包含视频,且视频每秒超过30帧,则应该选用该属性;
? ? ? ? 6、HDCP-LEVEL:该可选属性值是一个枚举字符串,取值为TYPE-0和NONE;取NONE时代表当前内容不受copy保护;取TYPE-0时,如果当前内容没有受到HDCP(High-bandwidth Digital Content Protection,高带宽数字内容保护)Type 0或同等级的保护,那么该可变流是无法播放的;
? ? ? ? 7、AUDIO:该可选属性的值是用引号括起来的字符串,且必须匹配主播放列表中TYPE属性为AUDIO的EXT-X-MEDIA标签的GROUP-ID属性的值,用于指示播放显示时应该使用的音频集;
? ? ? ? 8、VIDEO:该可选属性的值是用引号括起来的字符串,且必须匹配主播放列表中TYPE属性为VIDEO的EXT-X-MEDIA标签的GROUP-ID属性的值,用于指示播放显示时应该使用的视频集;
? ? ? ? 9、SUBTITLES:该可选属性的值是用引号括起来的字符串,且必须匹配主播放列表中TYPE属性为SUBTITLES的EXT-X-MEDIA标签的GROUP-ID属性的值,用于指示播放显示时应该使用的字幕集;
? ? ? ? 10、CLOSED-CAPTIONS:该可选属性的取值可以是带引号的字符串,也可以是值为NONE的枚举字符串;取值为带引号的字符串时,其必须匹配主播放列表中TYPE属性为CLOSED-CAPTIONS的EXT-X-MEDIA标签的GROUP-ID属性的值,用于指示播放显示时应该使用的关闭标题的显示集;如果取值为NONE,表明在主播放列表中的任何可变流中都没有Closed Captions;
? ? ? ? 当EXT-X-STREAM-INF标签包含AUDIO、VIDEO、SUBTITLES、或CLOSED-CAPTIONS属性时,表示其可用于播放该可变流的内容的替代译本,此时有这些约束:1、与EXT-X-STREAM-INF标签相关联的所有可播放的译本组合的带宽之和必须小于或等于EXT-X-STREAM-INF标签的BANDWIDTH属性;2、如果一个EXT-X-STREAM-INF标签包含一个RESOLUTION属性和一个VIDEO属性,那么每个用来替代的视频译本都要有对RESOLUTION对应的最佳分辨率;
????????如果媒体类型是Closed-caption,则EXT-X-MEDIA标签不能包含URI属性;如果媒体类型是SUBTITLES,EXT-X-MEDIA标记的URI属性是必需的;如果媒体类型是AUDIO或VIDEO,则URI是可选的,此时的URI如果缺省,那么当前译本的媒体数据包含在引用此EXT-X-MEDIA标记的任何EXT-X-STREAM-INF标记的媒体播放列表中;
EXT-X-I-FRAME-STREAM-INF ? ? ? ? 该标签定义一个包含多媒体显示I帧的媒体播放列表,它是独立的,因为它不应用于主播放器列表中的特定URI,其显示格式如下:
????????#EXT-X-I-FRAME-STREAM-INF:<attribute-list>,
????????除了FRAME-RATE、AUDIO、SUBTITLES和CLOSED-CAPTIONS外,EXT-X-STREAM-INF标签中的其他属性都适用于当前标签;此外,当前标签有一个单独的属性URI:其值是一个带引号的字符串,用于指定I帧媒体播放列表文件;
? ? ? ? 每个EXT-X-I-FRAME-STREAM-INF标签必须携带BANDWIDTH和URI属性;
? ? ? ? 指定可选视频译本和I帧播放列表的主播放列表,应该为每一个常规VIDEO译本,包含一个拥有相同NAME和LANGUAGE属性值的可选I帧视频译本;
EXT-X-SESSION-DATA ? ? ? ? 该标签允许在主播放列表中携带任意会话数据,该标签格式形如:
????????#EXT-X-SESSION-DATA:<attribute-list>,属性列表包含:
? ? ? ? 1、DATA-ID:该必选属性值是一个带引号的字符串,用于表示特定的数据值,取值遵循反向DNS命名约定,比如“com.example.movie.title”,但要避免冲突;
? ? ? ? 2、VALUE:该属性值是用引号括起来的字符串,它包含由Data-Id标识的数据,?如果指定了LANGUAGE, 那么VALUE应该包含一个用指定语言编写的可读字符串;
? ? ? ? 3、LANGUAGE:该可选属性的值是一个带引号的字符串,指示语言编号;
? ? ? ? 每个EXT-X-SESSION-DATA标签都应该包含一个VALUE或URI属性,但不能同时两个都包含;
????????一个播放列表可以包含多个带有相同DATA-ID属性的EXT-X-SESSION-DATA标签,?但不能包含多个带有相同DATA-ID属性和相同LANGUAGE属性的EXT-X-SESSION-DATA标签;
EXT-X-SESSION-KEY ? ? ? ? 该可选标签允许在主播放列表中指定媒体播放列表中的加密密钥,允许客户端预先加载这些密钥,而不必先读取媒体播放列表;该标签格式形如:#EXT-X-SESSION-KEY:<attribute-list>;
????????除了METHOD属性的值一定不能为NONE外,为EXT-X-KEY标签定义的所有属性也适用于当前标签;如果使用了当前标签,那么当前标签应该与具有相同URI的EXT-X-KEY标签拥有共同匹配的这些属性值:METHOD、KEYFORMAT、KEYFORMATVERSIONS;
????????如果多个可变流或译本使用相同的加密密钥和格式,则应该添加当前标签;
????????一个主播放列表不能包含一个以上具有相同METHOD、URI、IV、KEYFORMAT和KEYFORMATVERSIONS属性值的EXT-X-SESSION-KEY标签;
媒体播放列表标签或 主播放列表标签 EXT-X-INDEPENDENT-SEGMENTS ????????该标签指定一个媒体片段中不需要其他片段的信息就能被解码的媒体样本,它适用于播放列表中的每个媒体片段。如果该标签出现在主播放列表中,它将应用于主播放列表中每个媒体播放列表中的每个媒体片段;该标签格式形如:#EXT-X-INDEPENDENT-SEGMENTS;
EXT-X-START ? ? ? ? 该可选标签表示开始播放 播放列表的首选点,当开始一个播放会话时,客户端应该从该标签指定的位置开始播放;该标签格式形如:#EXT-X-START:<attribute-list>,包含如下几个属性:
? ? ? ? 1、TIME-OFFSET:该必选属性是以秒为单位的有符号浮点数,正数表示从播放列表开始的时间偏移量,负数表示距离播放列表中最后一个媒体片段末尾的负的时间偏移量;该属性的绝对值不应大于播放列表的时长,如果TIME-OFFSET的绝对值超过了播放列表的时长,它表示播放列表的结束(如果为正)或播放列表的开始(如果为负);如果播放列表不包含EXT-X-ENDLIST标签,那么TIME-OFFSET不应该在播放列表文件结束位置的三倍目标持续时间内;
? ? ? ? 2、PRECISE:该可选属性的值是一个枚举字符串,取值YES和NO。如果该属性缺省,那么应默认为NO;如果取值为NO,客户端应该尝试呈现该段中的每个媒体样本;如果取值为YES,客户端应该在TIME-OFFSET属性值指定的的媒体片段位置开始播放,但不应该在显示时间比TIME-OFFSET更早的片段中显示媒体样本;
? ? ? ? 注:关于最后的媒体播放列表标签或主播放列表标签类型 ,如果其中一个标签出现在主播放列表中,则不应出现在该主播放列表引用的任何媒体播放列表中,而且这些标签不能在播放列表中出现一次以上。
2.3、举例说明
? ? ? ? 2.3.1、主播放列表
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1280000,AVERAGE-BANDWIDTH=1000000
http://example.com/low.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2560000,AVERAGE-BANDWIDTH=2000000
http://example.com/mid.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=7680000,AVERAGE-BANDWIDTH=6000000
http://example.com/hi.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS="mp4a.40.5"
http://example.com/audio-only.m3u8
? ? ? ? 如上所示的代码段就是一个主播放列表(即一级M3U8)的简单例子,其中的#EXTM3U标签是每个M3U8文件所必须的基本标签,代表当前是一个媒体播放列表文件。之后的三个#EXT-X-STREAM-INF标签根据不同网络带宽,对同一个内容提供了高、中、低的三个不同码率的播放地址(即三个可变流)。最后一个#EXT-X-STREAM-INF标签则是通过CODECS属性指定了一个内容编码或封装格式是"mp4a.40.5"的纯音频播放地址。
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=1280000
low/audio-video.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=86000,URI="low/iframe.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=2560000
mid/audio-video.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=150000,URI="mid/iframe.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=7680000
hi/audio-video.m3u8
#EXT-X-I-FRAME-STREAM-INF:BANDWIDTH=550000,URI="hi/iframe.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS="mp4a.40.5"
audio-only.m3u8
????????如上所示,第二个M3U8文件内容主要是在第一个M3U8文件基础上,对每一个可变流都额外提供了一个携带I帧的播放地址。
#EXTM3U
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",NAME="English", \
DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="en", \
URI="main/english-audio.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",NAME="Deutsch", \
DEFAULT=NO,AUTOSELECT=YES,LANGUAGE="de", \
URI="main/german-audio.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="aac",NAME="Commentary", \
DEFAULT=NO,AUTOSELECT=NO,LANGUAGE="en", \
URI="commentary/audio-only.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS="...",AUDIO="aac"
low/video-only.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2560000,CODECS="...",AUDIO="aac"
mid/video-only.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=7680000,CODECS="...",AUDIO="aac"
hi/video-only.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=65000,CODECS="mp4a.40.5",AUDIO="aac"
main/english-audio.m3u8
? ? ? ? 如上所示的第三个M3U8文件内容中,#EXT-X-STREAM-INF标签提供的四个播放源由于携带了"AUDIO="aac"这个属性列表,于是在文件开头的三个#EXT-X-MEDIA标签中,通过指定TYPE属性为AUDIO、GROUP-ID属性为"aac"、LANGUAGE属性取不同值,来为这四个播放源提供不同语言的音频译本。其中第一个标签中属性列表【DEFAULT=YES,AUTOSELECT=YES】表示默认情况下选择LANGUAGE="en"的这个音频译本,即默认是英文音频。
#EXTM3U
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Main", \
DEFAULT=YES,URI="low/main/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Centerfield", \
DEFAULT=NO,URI="low/centerfield/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="low",NAME="Dugout", \
DEFAULT=NO,URI="low/dugout/audio-video.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=1280000,CODECS="...",VIDEO="low"
low/main/audio-video.m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Main", \
DEFAULT=YES,URI="mid/main/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Centerfield", \
DEFAULT=NO,URI="mid/centerfield/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="mid",NAME="Dugout", \
DEFAULT=NO,URI="mid/dugout/audio-video.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=2560000,CODECS="...",VIDEO="mid"
mid/main/audio-video.m3u8
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Main", \
DEFAULT=YES,URI="hi/main/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Centerfield", \
DEFAULT=NO,URI="hi/centerfield/audio-video.m3u8"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="hi",NAME="Dugout", \
DEFAULT=NO,URI="hi/dugout/audio-video.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=7680000,CODECS="...",VIDEO="hi"
hi/main/audio-video.m3u8
? ? ? ? 如上所示的第四个M3U8文件,则是根据#EXT-X-STREAM-INF标签指定的三个可变流的属性列表VIDEO="low"、VIDEO="mid"、VIDEO="hi",对每种可变流都由#EXT-X-MEDIA标签指定三个不同的视频译本。此时#EXT-X-MEDIA标签的TYPE属性必须是VIDEO、GROUP-ID属性必须和可变流的VIDEO属性值相同,然后取不同的NAME属性以区分不同的视频译本。
? ? ? ? 2.3.2、媒体播放列表
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXTINF:9.009,
http://media.example.com/first.ts
#EXTINF:9.009,
http://media.example.com/second.ts
#EXTINF:3.003,
http://media.example.com/third.ts
#EXT-X-ENDLIST
? ? ? ? 如上所示的代码段是一个媒体播放列表(即二级M3U8)文件的例子,其中标签#EXT-X-TARGETDURATION指定当前M3U8文件中,所有TS分片的最长时长为10秒;标签#EXT-X-VERSION指定当前M3U8使用的HLS协议版本号是3;标签#EXTINF指定每个TS分片的时长,其下一行跟随当前TS分片的访问地址;最后的#EXT-X-ENDLIST标签则是用来结束当前M3U8文件;
? ? ? ? 需要说明的是只有点播内容的媒体播放列表结尾才会有#EXT-X-ENDLIST标签,且该媒体播放列表所在的M3U8文件内容是不能更改的,客户端只需要请求一次该M3U8文件;直播内容媒体播放列表所在的M3U8文件末尾没有#EXT-X-ENDLIST标签,HLS直播的服务器只能不断更新这个M3U8文件,以在文件末尾追加新的直播TS分片,因而客户端需要每隔一段时间就重新请求一下该直播的M3U8文件,以下载后来追加的TS的分片;
三、对服务端、客户端的要求
3.1、服务端
? ? ? ? 这里的服务端指的是文章一开头直播链路图中的业务服务器,业务服务器相当于一个中转站,其输入是采集端推流来的媒体流,经过整理、转码、分割等操作,将媒体流根据不同流媒体传输协议输出给播放端。
? ? ? ? 3.1.1、对媒体片段的要求
将采集端推来的媒体流分割成一个个小的片段,分割时应以播放端能有效解码为依据,例如在PES包边缘或关键帧的地方进行分割; 针对每个媒体片段,都应该提供一个能有效访问的URI,使播放端能够通过HTTP协议有效访问和立即下载每个媒体片段; 如果服务器支持HTTP Range字段,即能够对服务器资源进行部分请求,那么HLS协议中就可以使用#EXT-X-BYTERANGE标签将媒体片段指定为较大媒体源的子范围;
? ? ? ? 3.1.2、对播放列表的要求
对于每个媒体源都应该创建一个媒体播放列表(即M3U8文件),文件中按顺序罗列每个携带有效URI的媒体片段; #EXT-X-PLAYLIST-TYPE标签值为VOD时代表点播媒体源,点播媒体源播放列表所在的M3U8文件是不能更改的,且该文件末尾应该提供#EXT-X-ENDLIST标签;#EXT-X-PLAYLIST-TYPE标签值为EVENT时代表直播媒体流,直播媒体流文件末尾不能有#EXT-X-ENDLIST标签。但需要服务端每隔一段时间对媒体播放列表进行更新,且更新动作只能是在文件末尾至少追加一个新的媒体片段。每更新一次媒体播放列表后,新版本的媒体播放列表的有效时间不能小于上一个版本有效时间的一半,不能大于上一版本的1.5倍,这样设定是为了约束播放列表的更新频率周期,使客户端能够以一个固定周期重新请求播放列表,以达到有效利用网络的目的。从播放端角度来看,这个更新动作需要是原子操作,否则会出现客户端与服务端媒体播放列表不一致; 如果服务器要下架或删除某个媒体源(访问会出现404或410),那么服务器需要在删除时,确保客户端下载的媒体播放列表在其有效时间范围内,能正常访问播放列表中的所有媒体片段,以防止客户端正在播放的内容突然中断;
? ? ? ? 3.1.4、对于部分标签的要求
关于序列号标签:无论是直播还是点播,播放列表中的#EXT-X-MEDIA-SEQUENCE标签或#EXT-X- DISCONTINUITY-SEQUENCE标签的值都应该是递增的; 关于目标时长标签:媒体播放列表中#EXT-X-TARGETDURATION标签的值是不能更改的,这个值一般取10秒; 关于不连续序列号标签:媒体播放列表中的每个媒体片段都有一个整数不连续序列号,这个序列号可以用来同步同一段内容的不同译本。一个媒体片段的不连续序列号的值 = #EXT-X-DISCONTINUITY-SEQUENCE标签的值(如果没有就取0)+ 该媒体片段URL行之前的#EXT-X-DISCONTINUITY标签的数量; 关于节目日期和时间标签:服务器可以通过使用#EXT-X-PROGRAM-DATE-TIME标签将绝对日期和时间与媒体片段关联起来,其主要是完成自然时间与媒体片段起始的时间映射。如果服务器提供了这种映射,那么就应该对每个使用了#EXT-X-PROGRAM-DATE-TIME标签的片段应用#EXT-X-DISCONTINUITY标签。需要注意的是#EXT-X-PROGRAM-DATE-TIME是一个媒体片段标签,所以他不能出现在媒体播放列表中,即M3U8文件开头的部分; 关于时间范围标签:如果一个播放列表范围内有任何的日期与时间映射到媒体片段,那么就不能从当前播放列表中删除#EXT-X-DATERANGE标签,且一个播放列表中各个#EXT-X-DATERANGE标签的ID属性不能重复。如果#EXT-X-DATERANGE标签携带了PLANNED-DURATION属性,即划定了DATERANGE的有效时长,那么就应该提供这个有效时间结束时的信号。比如添加另外一个具有相同ID属性的、相同DURATION或END-DATE属性的#EXT-X-DATERANGE标签。或者,如果当前#EXT-X-DATERANGE标签携带END-ON-NEXT=YES属性,那么就可以通过提供下一个新的DATERANGE的方式来结束前一个时间范围;
? ? ? ? 3.1.5、直播场景下的要求
直播场景下,服务器有可能会删除媒体播放列表中一些媒体片段的URI以限制其可用性,此时这个播放列表中必须包含#EXT-X-MEDIA-SEQUENCE标签。这些媒体片段必须按照它们在播放列表中出现的顺序从播放列表文件中删除,且他们的#EXT-X-MEDIA-SEQUENCE标签值必须是按顺序递增1。 当服务器从列表中删除一个媒体片段时,这个媒体片段必须在一段时间内对客户端保持可用,该时间等于该片段段的持续时间加上包含该片段的最长播放列表文件的持续时间。 一个媒体播放列表没有以#EXT-X-ENDLIST标签结束(即直播)的情境下,如果当前播放列表的总时长小于该列表中#EXT-X-TARGETDURATION标签指定的目标时长的三倍,那么就不能再删除播放列表中的任何媒体片段了; 如果服务器计划在通过HTTP传输到客户端后删除某个媒体片段,那么应该确保HTTP响应包含一个Expires头,以指示这个媒体片段的过期时间; 如果服务器希望从包含#EXT-X-DISCONTINUITY标签的媒体播放列表中删除媒体片段,那么这个媒体播放列表中必须包含#EXT-X-DISCONTINUITY-SEQUENCE标签,否则客户端将无法在各个译本中找到对应的媒体片段,即无法同步。 如果服务器从媒体播放列表中删除了EXT-X-DISCONTINUITY标签,那么就必须增加#EXT-X-DISCONTINUITY-SEQUENCE标签的值,以保证播放列表中仍然存留的媒体片段的不连续序列号保持不变;
? ? ? ? 3.1.6、加密相关的要求
媒体片段是可以加密的,每个加密的媒体片段必须有一个#EXT-X-KEY标签和一个URI,客户端可以根据URI获取一个解密密钥文件; 一个媒体片段只能用一个加密算法加密,即使用一个加密密钥和IV加密。但服务器可通过提供多个拥有不同KEYFORMAT属性值的#EXT-X-KEY标签,来提供多种检索密钥的方法; 服务器可以在密钥响应中设置HTTP Expires头来指定密钥可以缓存的时间; 在播放列表中,如果一个未加密的媒体片段前面有一个加密了的媒体片段,那么这个未加密的媒体片段需要添加一个METHOD属性为NONE的#EXT-X-KEY标签,以防止客户端将其误解为加密的媒体片段; 如果一个播放列表中包含任何一个携带#EXT-X-KEY标签的媒体片段,那么服务器就不能从播放列表文件中删除该标签,否则随后加载该播放列表的客户端将无法解密这些媒体片段;
? ? ? ? 3.1.7、可变流的要求
? ? ? ? 如果一个服务器可以提供多个媒体播放列表文件来为相同的显示内容提供不同的码率效果,那么也应该提供一个列出每个可变流的主播放列表文件,以允许客户端在不同编码之间动态切换。为了尽可能达到无缝切换,需要满足如下要求:
每个可变流必须显示相同的内容,且各个可变流中时间戳、不连续序列号、目标时长必须相同; 在一个可变流中会出现、但在另外一个可变流中不会出现的内容,必须出现在播放列表的开头或结尾的位置,且时长不能超过播放列表的目标时长; 如果任何一个媒体播放列表中有一个#EXT-X-PLAYLIST-TYPE标签,那么所有的媒体播放列表都必须具有相同值的#EXT-X-PLAYLIST-TYPE标签。如果播放列表包含一个带有VOD值的#EXT-X-PLAYLIST-TYPE标签,则每个可变流中的每个媒体播放列表的第一个片段必须从相同的媒体时间戳开始; 如果主播放列表中的任何一个媒体播放列表包含EXT-X-PROGRAM-DATE-TIME标签,那么该主播放列表中的所有媒体播放列表都必须包含这个具有日期和时间到媒体时间戳一致映射的标签; 每个可变流必须包含相同的时间范围,这个范围由具有相同的ID属性值的、包含相同属性列表的#EXT-X-DATERANGE标签标识;
3.2、客户端
? ? ? ? 3.2.1、加载媒体播放列表
客户端通过HTTP协议根据URI从服务器下载媒体播放列表,如果是一个主播放列表,则需要在提供的可变流中选择一个媒体播放列表进行下载、解析,解析媒体播放列表文件时需要忽略任何无法识别的标签和属性列表; 如果媒体播放列表包含#EXT-X-MEDIA-SEQUENCE标签,客户端应该假设在播放列表文件加载的时间及其持续时间内,其中的每个媒体片段都是不可用的; 当同一个播放列表重新加载时,客户端可以使用序列号来跟踪播放列表中媒体片段的位置。但因为不同可变流的媒体播放列表中可能有独立的媒体序列号,所以客户端不能假设不同变体流或译本中具有相同媒体序列号的片段在显示内容中具有相同的位置。此时,客户端应该使用每个片段在播放列表时间轴上的相对位置和它的不连续序列号来定位相应的片段; 客户端必须加载每个播放选择的译本的媒体播放列表文件,以便定位该播放译本的媒体。但是,为了防止服务器上不必要的加载,客户端不应该加载任何其他译本的播放列表文件。对于某些变体流,可以选择不包含#EXT-X-STREAM-INF标签指定的译本; 客户端必须在每次加载或重新加载媒体播放列表文件时检查该文件,以确定下一个要加载的媒体片段。第一个加载的片段通常是客户端选择先播放的片段,而一般情况下,下一个要加载的媒体片段是媒体序列号最低的那个,它大于上一个加载的媒体片段的媒体序列号;
? ? ? ? 3.2.2、播放媒体播放列表
开始播放时,客户端应该从媒体播放列表中选择首先播放哪个媒体片段。正常播放情况下,可以通过按媒体片段在播放列表中出现的顺序来播放。如果播放列表中不存在EXT-X-ENDLIST标签,为了正常播放,客户端不应该选择一个从起始位置到播放列表末尾总时长小于三倍目标时长(媒体播放列表的Target Duration)的片段开始播放; 在一个媒体片段中以及在一个媒体播放列表中的多个媒体段中,样本的编码参数应该保持一致。?然而,客户应该在遇到编码变化时处理它们,例如,通过缩放视频内容来适应分辨率的变化。?如果可变流包含分辨率属性,客户端应该在矩形框内显示所有与该分辨率属性值相同的视频; 客户端应该准备好处理特定类型的多个轨道(例如音频或视频),没有其他偏好的客户端应该选择其可以播放的最低数字轨道标识符的轨道; 客户端应该忽略传输流中他们不认识的私有流,虽然私有流可以用来支持相同流的不同设备,但是也会增加额外的网络负载;?? 在播放带有#EXT-X-DISCONTINUITY标签的媒体段之前,客户端必须准备好重置其解析器和解码器; 客户端应该尝试在媒体片段需要不间断播放之前加载它们,以补偿延迟和吞吐量的临时变化; 客户端可以使用#EXT-X-PROGRAM-DATE-TIME标签的值向用户展示节目起始时间,如果该时间包含时区信息,客户端可以考虑展示,否则应该展示本地时间;需要注意的是,播放列表中的日期与时间是指内容产生的时间(或其他时间),其与播放时间无关; 如果播放列表中的第一个#EXT-X-PROGRAM-DATE-TIME标签出现在一个或多个媒体片段URI之后,客户端应该使用#EXTINF时长和/或媒体时间戳从该标签向后(时间轴较早的一端)推断,以将日期与这些段关联起来。如果要将一个日期与任何其他没有直接应用#EXT-X-PROGRAM-DATE-TIME标签的媒体片段关联,客户端应该从播放列表中出现在该片段之前的最后一个#EXT-X-PROGRAM-DATE-TIME标签向前(时间轴较晚的一端)推断;
? ? ? ? 3.2.3、重新加载媒体播放列表
客户端必须定期重新加载媒体播放列表文件,以了解哪些媒体是当前可用的。除非该播放列表包含一个值为VOD的#EXT-X-PLAYLIST-TYPE标签,或者包含一个值为EVENT的#EXT-X-PLAYLIST-TYPE标签并且EXT-X-ENDLIST标签也同时存在。即点播情况下无需重新加载,直播才需要重新加载; 当客户端首次或重新加载一个播放列表文件时,如果发现该播放列表文件自最后一次加载后已经发生了改变,那么自客户端最后一次加载播放列表文件后开始,需要至少等待目标持续时间(Target Duration)后,再重新尝试加载该播放列表文件;如果发现它没有改变,那么必须等待目标持续时间的一半后再重新尝试。除此以外更高的重新加载频率会增加服务端的网络压力; 在重新加载媒体播放列表后,客户端应该验证其中的每个媒体片段与前一个媒体播放列表中具有相同媒体序列号的媒体片段是否具有相同的URI(和字节范围,如果指定了的话)。如果不相同,客户端应该停止播放,因为这通常表明服务端发生了错误; 为了减少服务器负载,客户端不应该重新加载当前未播放的可变流或可选译本的播放列表文件。?如果客户端决定切换到一个不同的可变流播放,那么就应该停止重新加载旧可变流的播放列表,并且开始加载新可变流的播放列表;
四、协议版本兼容情况
????????协议兼容性由#EXT-X-VERSION标签指定,默认为1,?包含与协议版本1不兼容的标签或属性的播放列表必须包含#EXT-X-VERSION标签。不同版本内容更新迭代情况如下:
Version 1:最低默认版本; Version 2:#EXT-X-KEY标签新增了IV属性; Version 3:#EXTINF标签的时长数值新增了浮点类型; Version 4:新增了#EXT-X-BYTERANGE标签和#EXT-X-I-FRAMES-ONLY标签; Version 5:新增了#EXT-X-MAP标签,以及#EXT-X-KEY标签新增了KEYFORMAT和KEYFORMATVERSIONS属性; Version 6:媒体播放列表中不再包含EXT-X-I-FRAMES-ONLY的#EXT-X-MAP标签、删除了#EXT-X-STREAM-INF标签的PROGRAM-ID属性、删除了#EXT-X-I-FRAME-STREAM-INF标签; Version 7:#EXT-X-MEDIA标签的INSTREAM-ID属性新增一个值:"SERVICE"、删除了#EXT-X-ALLOW-CACHE标签;