M3U8 格式:为什么直播回放都用这个格式?丨音视频基础

(本文基本逻辑:M3U8 封装格式概览 → M3U8 格式解析 → M3U8 封装示例)

M3U 文件是一种纯文本文件,可以指定一个或多个多媒体文件的位置。它的设计初衷是为了播放音频文件,但后来越来越多的用于播放视频文件列表。而 M3U8 则是用 UTF-8 编码的 M3U。M3U、M3U8 文件都是苹果公司使用的 HLS(HTTP Live Streaming) 协议的基础。

在实际应用场景中,由于 HLS/M3U8/TS 这套方案在控制直播延时上不太理想,所以一般实时直播场景不会选择使用 M3U8 媒体格式。但是,对于直播回放这种场景,由于使用 M3U8/TS 这套方案能够在直播过程中就持续生成和存储切片,所以直播回放基本上都会选择 M3U8 媒体格式。

1、M3U8 格式概览

M3U8 文件其实是一个播放列表,这个列表可能是一个媒体播放列表(Media Playlist),也可能是一个主播放列表(Master Playlist)。但无论是哪种播放列表,其内部文字使用的都是 utf-8 编码。

1.1、媒体播放列表

当 M3U8 文件作为媒体播放列表(Meida Playlist)时,其包含的信息记录的是一系列多媒体资源切片,顺序播放这些切片,即可完整呈现多媒体资源。

第一行的 #EXTM3U 表示文件格式。第二行的 #EXT-X-TARGETDURATION:10 表示后面的各个资源切片时长都小于或等于 10 秒。接下来,我们看到有 3 个资源切片,时长分别是 9.009 秒、9.009 秒、3.003 秒。

在点播时,客户端首先下载 M3U8 文件,然后按照 M3U8 列表下载各个资源切片依次播放即可。在直播时,客户端则需要定时重新请求 M3U8 文件,从而检查是否有新的媒体切片需要进行下载播放。所有的这些数据都通过 HTTP 协议传输。

1.2、主播放列表

当 M3U8 文件作为主播放列表(Master Playlist)时,其包含的信息是同一个媒体资源的多路流资源列表。不同的流可能有着不同的码率,不同的格式,不同的分辨率。不同的流也可以指定不同语言的音频,不同视角的视频等等。

客户端应该根据网络状况来选择合适的流来播放,也应该根据用户的偏好来选择合适的语言和视角的流来播放。

2、M3U8 格式解析

这里讲的播放列表文件主要是指 HLS 协议所使用的播放列表文件,该文件的格式主要包含下面几方面的内容:

  • 格式规范
  • 属性列表
  • 标签

2.1、格式规范

M3U8 播放列表文件必须以 UTF-8 进行编码,不能包含任何 Byte Order Mark(BOM)内容,并且除了 CR(U+000D) 和 LF(U+000A) 之外不能包含任何 UTF-8 控制字符 (U+0000 ~ U+001F 及 U+007F ~ U+009F)。并且,所有的字符序列必须遵循 Unicode 规范。

M3U8 播放列表文件的每一行要么是一个 URI,要么是空行,要么是以 # 开头的字符串。空行会被忽略,除了显式声明的元素,不能出现空白字符。

# 开头的字符串要么是注释,要么是标签。标签以 #EXT 开头,大小写敏感。以 # 开头的注释在解析时应该忽略。

如果 M3U8 文件是一个媒体播放列表(Meida Playlist),那么每个 URI 对应的都是一个媒体切片;如果 M3U8 文件是一个主播放列表(Master Playlist),那么每个 URI 对应的是一个媒体播放列表。其他表示都是不正确的。

一个媒体播放列表的时长等于它包含的所有媒体切片时长的总和。

每个媒体切片的码率等于切片的大小除以它的时长。需要注意的是,这里及后面码率的计算包含了除了音视频数据外的容器数据,但是不包含各种传输协议(HTTP、TCP、IP)头所占用的数据。

一个媒体播放列表的最高码率是所有切片中码率的最大值,但这里的切片需要满足条件:时长是 #EXT-X-TARGETDURATION 指定值的 0.5 ~ 1.5 倍的连续切片。

一个媒体播放列表的平均码率是所有切片的大小之和(单位:bit)除以播放列表的时长。

2.2、属性列表

属性列表是一组可以设置值的特定标签,它们对应的是一个个的键值对,语法如下:

AttributeName=AttributeValue
这里的属性名和属性值都不能包含空白字符。属性名允许的字符集是 [A..Z] + [0..9] + -。一个属性名只能出现一次。属性值也需要遵循一定的规范。

 【免费分享】音视频资料领取,见文章最后。

2.3、标签

播放列表的标签用于指定文件的全局信息,或者指定跟在其后的媒体切片或媒体播放列表的相关信息。

2.3.1、基础标签(Basic Tags)

基础标签(Basic Tags)可以在媒体播放列表(Media Playlist)和主播放列表(Master Playlist)中使用。

  • EXTM3U,表示文件继承自 M3U 标准。这个标签必须放在文件第一行。
  • EXT-X-VERSION,表示文件的版本,这个与文件相关的媒体和服务器相关。
    • 语法:#EXT-X-VERSION:<n>

2.3.2、媒体切片标签(Media Segment Tags)

每个切片 URI 前面都有一组媒体切片标签(Media Segment Tags)对其进行描述。有一些媒体切片标签只对跟在其后的一个媒体切片相关;有的则与其后的所有切片都相关,直到后面遇到另一个该标签的描述。

媒体切片标签不能出现在主播放列表(Master Playlist)中。

  • EXTINF,表示其后媒体切片的时长(单位为秒)。每个媒体切片之前必须指定该标签。
    • 语法:#EXTINF:<duration>,[<title>]
  • EXT-X-BYTERANGE,表示指定媒体切片是其后 URI 指定的媒体资源的一部分。
    • 语法:#EXT-X-BYTERANGE:<n>[@<o>]
    • 说明:其中 n 表示字节大小,o 表示起始位置。如果指定了 o 值,则表示对 URI 指定资源从 o 指定的位置开始截取 n 字节;如果 o 未指定,则表示把上一个该标签指定的媒体资源作为目标,将其已截取片段的下一个字节作为起始位置开始再截取 n 字节。如果没有指定该标签,则表明切片范围为整个 URI 指定的媒体资源。该标签兼容的版本是 EXT-X-VERSION 为 4 及以上。
  • EXT-X-DISCONTINUITY,表示其前一个切片和下一个切片之间存在中断。在媒体文件格式、媒体轨道的数量和类型、时间戳序列、编码参数、编码序列的内容发生变化时,需要使用该标签。
  • EXT-X-KEY,媒体切片是可以加密的,这个标签用来指定解密方法。
    • 语法:#EXT-X-KEY:<attribute-list>
    • 说明:一般一个媒体播放列表中会出现 2 个以上的 EXT-X-KEY 标签,一个 EXT-X-KEY 标签作用于包含在它和下一个具有同样 KEYFORMAT 属性值的 EXT-X-KEY 标签之间的所有切片。
  • EXT-X-MAP,指定了如何获取媒体初始化信息(Meida Initialization Section)来解析后续的媒体切片数据。该标签对其后所有切片生效,直到遇到下一个 EXT-X-MAP 标签。
    • URI,这个字段是必须的,该 URI 指向包含媒体初始化信息(Meida Initialization Section)资源。
    • BYTERANGE,该字段是可选的,表示上面 URI 指向的资源中媒体初始化信息(Meida Initialization Section)的精确字节位置。如果没有该字段,则表示该资源所有的数据都是目标数据。
    • 语法:#EXT-X-MAP:<attribute-list>,这里的属性列表包括如下字段:
  • EXT-X-PROGRAM-DATE-TIME,使用了一个绝对的时间来指定媒体切片第一个采样的时间。这个标签只作用于其后的一个切片。
    • 语法:#EXT-X-PROGRAM-DATE-TIME:<date-time-msec>
  • EXT-X-DATERANGE,用于将一个时间范围和一组属性关联起来。

2.3.3、媒体播放列表标签(Media Playlist Tags)

媒体播放列表标签(Media Playlist Tags)主要用来描述全局的媒体信息。

  • EXT-X-TARGETDURATION,表示所有媒体切片的最大时长,单位是秒。这个标签是必填的。EXTINF 所指定的各个切片的时长必须不大于这个时长,否则会出现播放卡顿或播放错误。
    • 语法:#EXT-X-TARGETDURATION:<s>
  • EXT-X-MEDIA-SEQUENCE,表示列表文件中第一个媒体切片的序号。如果没有这个标签,那么表示第一个媒体切片的序号为 0。每个媒体切片都有唯一的序列号,序列号按照出现顺序依次加 1。此外,如果有这个标签,那么这个标签需要放在第一个切片之前。
    • 语法:#EXT-X-MEDIA-SEQUENCE:<number>
  • EXT-X-DISCONTINUITY-SEQUENCE,该标签用于同步相同流的不同路或者有 EXT-X-DISCONTINUITY 标签的不同备份流。该标签必须出现在第一个切片之前,且必须出现在任何 EXT-X-DISCONTINUITY 标签之前。
    • 语法:#EXT-X-DISCONTINUITY-SEQUENCE:<number>
  • EXT-X-ENDLIST,表示不会再有更多的切片会添加到播放列表中。该标签可以出现在媒体播放列表的任意位置,一般出现在文件结尾。
    • 语法:#EXT-X-ENDLIST
  • EXT-X-PLAYLIST-TYPE,该标签表明了全局播放列表的可变性。这个标签是可选的,作用于整个播放列表。该标签如果被省略,则媒体播放列表是可以修改的。
    • 语法:#EXT-X-PLAYLIST-TYPE:<EVENT|VOD>
    • 说明:EVENT 表示可以在播放列表可变,不过只能在尾部添加媒体切片;VOD 表示播放列表不可变。
  • EXT-X-I-FRAMES-ONLY,该标签表示每个媒体切片都是 I 帧。该标签作用于整个播放列表。
    • 语法:#EXT-X-I-FRAMES-ONLY
    • 说明:在包含 EXT-X-I-FRAMES-ONLY 切片的播放列表中,每个切片的时长(EXTINF)表示当前 I 帧开始到下一个 I 帧开始的时间。媒体资源如果是 I 帧切片,那么必须在开始位置提供 Media Initialization Section 信息或者通过 EXT-X-MAP 标签提供 Media Initialization Section 的获取路径,这样客户端就在任意位置以任意顺序来对这些 I 帧进行解码。如果 I 帧切片设置了 EXT-X-BYTERANGE 标签,那么它对应的数据长度一定不能包含 Media Initialization Section 的数据长度。客户端可以认为 Media Initialization Section 信息是定义在 EXT-X-MAP 标签中的,或者它的位置是从切片起始的位置开始到第一个 I 帧起始的位置结束。兼容 EXT-X-I-FRAMES-ONLY 要求文件版本号 EXT-X-VERSION 大于等于 4。

2.3.4、主播放列表标签(Master Playlist Tags)

主播放列表标签(Master Playlist Tags)主要用于定义多路流以及其他全局参数。主播放列表标签不能出现在媒体播放列表中。

  • EXT-X-MEDIA,该标签用于指定具有相同内容的不同路的流,这些流可能是有不同的音视频参数,或者是对应不同的语言翻译。比如,我们可以通过 3 个 EXT-X-MEDIA 标签来给一个媒体资源分别指定英语、法语、西班牙语的音频内容;我们也可以通过 2 个 EXT-X-MEDIA 标签给一个媒体资源指定两种不同的拍摄视角。
    • TYPE,资源类型。必填字段,可选值有:AUDIOVIDEOSUBTITLESCLOSED-CAPTIONS。一般隐藏式字幕(CLOSED-CAPTIONS)是跟着视频数据的,不会专门指定一路流。
    • URI,资源地址。可选字段,如果 TYPE 是 CLOSED-CAPTIONS,则不要出现这个字段。
    • GROUP-ID,分组标识。必填字段,用于指定资源属于哪个组。
    • LANGUAGE,指定资源主要使用的语言。可选字段。
    • ASSOC-LANGUAGE,指定资源使用的语言的一个版本,常用来指定语言的书写、方言等特效。可选字段。
    • NAME,用于填写名字,目的是易读。必填字段。
    • DEFAULT,表示当前资源是否是默认播放资源。可选字段,默认值是 NO。
    • AUTOSELECT,可选字段,默认值为 NO。当该值为 YES,当用户没有指定偏好时,则默认播放这个资源。如果有该字段,并且 DEFAULT 值为 YES 时,该值必须为 YES。
    • FORCED,可续字段,默认值为 NO。只有当 TYPE 值为 SUBTITLES 时,才能出现该字段。当该值为 YES,表示资源中包含了重要的内容,客户端应该从中选择最符合当前播放环境的资源来播放。
    • INSTREAM-ID,只有当 TYPE 为 CLOSED-CAPTIONS 才出现该字段,且必须出现。
    • CHARACTERISTICS,可选字段。
    • CHANNELS,当 TYPE 为 AUDIO,该字段表示音频轨道数。
    • 语法:#EXT-X-MEDIA:<attribute-list>,其中这里的属性列表包括:
    • 说明:同一组的资源都有同样的 GROUP-ID 和同样的 TYPE,同一组的不同路流必须对应的是统一的内容,否则播放可能会出错。一个播放列表的所有 EXT-X-MEDIA 的 NAME 属性都必须各不相同。同一组中只能有一个 DEFAULT 属性为 YES 的 EXT-X-MEDIA。AUTOSELECT 为 YES 的不同 EXT-X-MEDIA 必须能通过 LANGUAGE、ASSOC-LANGUAGE、FORCED、CHARACTERISTICS 属性组做出区分。
  • EXT-X-STREAM-INF,该标签用于指定媒体资源的具体信息。
    • BANDWIDTH,表示流的最高码率(Peak Segment Bit Rate),包含了所有需要播放的媒体资源的码率加和。必填字段。
    • AVERAGE-BANDWIDTH,表示流的平均码率。可选字段。
    • CODECS,表示编码器。应该尽量包含该字段。
    • RESOLUTION,表示分辨率。可选字段。
    • FRAME-RATE,表示帧率。可选字段。但是包含视频的资源都应该尽量包含该信息。
    • HDCP-LEVEL,表示数字内容保护。可选字段。
    • AUDIO,对应某个 TYPE 为 AUDIO 的 EXT-X-MEDIA 标签的 GROUP-ID 字段。表示音频应该使用对应组的资源。可选字段。
    • VIDEO,对应某个 TYPE 为 VIDEO 的 EXT-X-MEDIA 标签的 GROUP-ID 字段。表示视频应该使用对应组的资源。可选字段。
    • SUBTITLES,对应某个 TYPE 为 SUBTITLES 的 EXT-X-MEDIA 标签的 GROUP-ID 字段。表示字幕应该使用对应组的资源。可选字段。
    • CLOSED-CAPTIONS,对应某个 TYPE 为 CLOSED-CAPTIONS 的 EXT-X-MEDIA 标签的 GROUP-ID 字段。表示隐藏字幕应该使用对应组的资源。可选字段。
    • 语法:#EXT-X-STREAM-INF:<attribute-list> <URI>,URI 是换行。这里的属性列表包括:
  • EXT-X-I-FRAME-STREAM-INF,表示一个包含 I 帧的媒体播放列表。这个标签是独立的,不作用于主播放列表里的其他资源。该标签主要服务于播放时的快进和快退功能。
    • URI,对应一个只包含 I 帧的媒体播放列表。该列表中必须包含 EXT-X-I-FRAMES-ONLY 标签。
    • 语法:#EXT-X-I-FRAME-STREAM-INF:<attribute-list>,属性列表包含了上文所讲的 EXT-X-STREAM-INF 标签除了 FRAME-RATE、AUDIO、SUBTITLES、CLOSED-CAPTIONS 外的各属性,同时再增加下列属性:
    • 说明:每个 EXT-X-I-FRAME-STREAM-INF 必须包含 BANDWIDTH 和 URI 属性。对于主列表中包含的多路流,则应该对应多路 I 帧媒体播放列表,且为它们设置同样的 NAME 和 LANGUAGE 属性。
  • EXT-X-SESSION-DATA,该标签允许在主播放列表中携带任意的会话数据。
    • DATA-ID,ID 最好遵循类似 com.example.movie.title 格式。必填字段。
    • VALUE,数据值。VALUE 字段和 URI 字段二选一。
    • URI,数据地址,应该指向一个 JSON 文件。VALUE 字段和 URI 字段二选一。
    • LANGUAGE,语言。可选字段。
    • 语法:#EXT-X-SESSION-DATA:<attribute-list>,属性列表包括:
    • 说明:一个主播放列表可以包含多个有同样 DATA-ID 的 EXT-X-SESSION-DATA 标签,但是不能包含一个以上的有同样 DATA-ID 和 LANGUAGE 的 EXT-X-SESSION-DATA 标签。
  • EXT-X-SESSION-KEY,该标签允许将加密秘钥放在主播放列表中,这样客户端可以预先加载主播放列表类提取获取到加密秘钥,而不用非要加载媒体播放列表来获取。
    • 语法:#EXT-X-SESSION-KEY:<attribute-list>

2.3.5、播放列表共用标签(Media or Master Playlist Tags)

有一些标签是媒体播放列表和主播放列表中都可以出现的,但是一般一个标签出现在主播放列表,那么就不要再在该主播放列表索引的媒体播放列表中出现了。如果一定要两边都出现,那么标签对应的值必须相同,否则客户端应该忽略媒体播放列表的值,采用主播放列表的值。在同一个播放列表中,这些标签一定不能出现多次。

  • EXT-X-INDEPENDENT-SEGMENTS,表明列表中的所有切片都可以独立解码,无需依赖其他切片的信息。
    • 语法:#EXT-X-INDEPENDENT-SEGMENTS
    • 说明:如果该标签出现在主播放列表,则适用于主播放列表包含的所有媒体播放列表。
  • EXT-X-START,表明倾向于从哪个时间点开始播放。
    • TIME-OFFSET,表示开始时间偏移,必填字段。如果是正数,则表示距离播放开始时间的偏移,此时如果绝对值超过了视频总时长则表示偏移到结束时间;如果是负数,则表示是距离播放结束时间的偏移,此时如果绝对值超过了视频总时长则表示偏移到开始时间。如果播放列表不包含 EXT-X-ENDLIST 标签,则 TIME-OFFSET 的值不应该在播放列表末尾的 3 个切片的时长之内。
    • PRECISE,表示是否精确,可选字段。默认是 NO。如果设置该值为 YES,则客户端应该播放时间包含 TIME-OFFSET 的切片,并且不要渲染该切片内时间在 TIME-OFFSET 之前的采样;如果该值为 NO,则渲染切片内所有的采样。
    • 语法:#EXT-X-START:<attribute-list>,属性列表包括:

3、实战解析

1)一个点播媒体播放列表:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#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 文件支持绝对路径,也支持相对路径,所以上面的格式等效于:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXTINF:9.009,
first.ts
#EXTINF:9.009,
second.ts
#EXTINF:3.003,
third.ts
#EXT-X-ENDLIST

上面的示例是一个典型的点播媒体播放列表,主要特征是:

  • 文件包含 EXT-X-ENDLIST 标签。
  • EXT-X-PLAYLIST-TYPE 标签(可选)值为 VOD,表示播放列表不可变。

2)一个 EVENT 播放列表:

刚开始时,对应的 M3U8 文件内容如下所示:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10,
fileSequence0.ts
#EXTINF:10,
fileSequence1.ts
#EXTINF:10,
fileSequence2.ts
#EXTINF:10,
fileSequence3.ts

EVENT 播放列表的主要特征是:

  • EXT-X-PLAYLIST-TYPE 标签值为 EVENT,表示播放列表内容可变,不过只能在文件末尾改变。

结束时,M3U8 文件内容如下所示:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:EVENT
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10,
fileSequence0.ts
#EXTINF:10,
fileSequence1.ts
#EXTINF:10,
fileSequence2.ts
#EXTINF:10,
fileSequence3.ts
...
#EXTINF:10,
fileSequence120.ts
#EXTINF:10,
fileSequence121.ts
#EXT-X-ENDLIST

EVENT 播放列表可以用在直播中,通常用于晚会和体育赛事场景,用户一方面可以观看直播,一方面还能做 seek 操作回退到之前的时间点去回放。

3)一个直播播放列表:

直播过程中某个时间点的 M3U8 文件内容:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:2680

#EXTINF:7.975,
https://priv.example.com/fileSequence2680.ts
#EXTINF:7.941,
https://priv.example.com/fileSequence2681.ts
#EXTINF:7.975,
https://priv.example.com/fileSequence2682.ts

M3U8 文件可以使用 HTTP,也可以使用 HTTPS。

直播播放列表的主要特征:

  • 不包含 EXT-X-ENDLIST 标签。
  • 不包含 EXT-X-PLAYLIST-TYPE 标签。

直播播放列表是一个会动态更新的 M3U8 文件,服务端会对直播流进行实时转码生成直播流切片,并定期更新 M3U8 文件。这个 M3U8 文件一般为会包括 3-5 个切片。

直播播放列表中的任意一个切片的 URI 被移除时,都需要更新 EXT-X-MEDIA-SEQUENCE 标签的值(+1)。移除切片 URI 时必须按顺序,以保证客户端通过更新的 M3U8 文件拿到的是连续的切片数据。

当上面的实例更新一个切片后,M3U8 文件内容更新为:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:8
#EXT-X-MEDIA-SEQUENCE:2681

#EXTINF:7.941,
https://priv.example.com/fileSequence2681.ts
#EXTINF:7.975,
https://priv.example.com/fileSequence2682.ts
#EXTINF:7.971,
https://priv.example.com/fileSequence2683.ts

4)一个加密的媒体播放列表:

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:7794
#EXT-X-TARGETDURATION:15

#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52"

#EXTINF:2.833,
http://media.example.com/fileSequence52-A.ts
#EXTINF:15.0,
http://media.example.com/fileSequence52-B.ts
#EXTINF:13.333,
http://media.example.com/fileSequence52-C.ts

#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=53"

#EXTINF:15.0,
http://media.example.com/fileSequence53-A.ts

主要特征:

  • 包含 EXT-X-KEY 标签。

上面示例中的 #EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52" 加密信息作用于 fileSequence52-A.tsfileSequence52-B.tsfileSequence52-C.ts 这 3 个切片。

5)一个 BYTERANGE 播放列表:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:4
#EXTINF:9.009,
#EXT-X-BYTERANGE:752320
media.ts
#EXTINF:9.009,
#EXT-X-BYTERANGE:82112@752321
media.ts
#EXTINF:3.003,
#EXT-X-BYTERANGE:69864
media.ts
#EXT-X-ENDLIST

主要特征:

  • EXT-X-VERSION 标签的值为 4 以上,确保 HLS 支持。
  • 通过 EXT-X-BYTERANGE 来指定切片偏移量。语法是:#EXT-X-BYTERANGE:length[@offset]

使用 BYTERANGE 播放列表可以不用在服务端存储大量的小切片文件,只通过一个文件再加上文件偏移量信息就可以支持分片。

比如,上面示例的 BYTERANGE 播放列表等价于下面简单的播放列表:

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXTINF:9.009,
first.ts
#EXTINF:9.009,
second.ts
#EXTINF:3.003,
third.ts
#EXT-X-ENDLIST

6)一个插播不同格式内容的播放列表:

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10.0,
ad0.ts
#EXTINF:8.0,
ad1.ts
#EXT-X-DISCONTINUITY
#EXTINF:10.0,
movieA.ts
#EXTINF:10.0,
movieB.ts

主要特征:

  • 包含 EXT-X-DISCONTINUITY 标签。

在一些场景下,我们需要在点播或直播中插入其他内容,比如广告,这时候可能这段广告内容的编码格式与原视频的编码格式存在差异,这种差异可能造成客户端播放出问题,这时候就需要告知客户端。这就需要用到 EXT-X-DISCONTINUITY 标签。

7)一个主播放列表:

#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

主要特征:

  • 包含 EXT-X-STREAM-INF 标签。

上面示例中,通过 3 个不同码率的视频流和 1 个音频流来描述一个内容。

8)I 帧播放列表:

#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

主要特征:

  • 包含 EXT-X-I-FRAME-STREAM-INF 标签。

HLS 是通过主播放列表标签 EXT-X-I-FRAME-STREAM-INF 和媒体播放列表标签 EXT-X-I-FRAMES-ONLY 配合来实现 I 帧播放列表,从而支持视频播放常用的快进和快退功能。

上面的示例是在主播放列表中通过 EXT-X-I-FRAME-STREAM-INF 标签指定 I 帧播放列表,那么对应的 I 帧播放列表内容示例如下:

#EXTM3U
#EXT-X-VERSION:4
#EXT-X-I-FRAMES-ONLY
...
#EXTINF:4.12,
#EXT-X-BYTERANGE:9400@376
segment1.ts
#EXTINF:3.56,
#EXT-X-BYTERANGE:7144@47000
segment1.ts
#EXTINF:3.82,
#EXT-X-BYTERANGE:10340@1880
segment2.ts

主要特征:

  • EXT-X-VERSION 标签的值为 4 以上,确保 HLS 支持。
  • 包含 EXT-X-I-FRAMES-ONLY 标签。

上面的示例是用 EXT-X-BYTERANGE 来指定每个 I 帧对应的数据。这里需要注意的是 EXTINF 表示的时长是当前 I 帧到下一个 I 帧的时长。

9)Alternate Media 主播放列表:

包含多路音频的主播放列表:

#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

包含多路视频的主播放列表:

#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

为了节省空间,其中 CODECS 字段被省略了。

主要特征:

  • 包含 EXT-X-MEDIA 标签,来对描述相同资源的流进行分组。
  • EXT-X-STREAM-INF 增加了 VIDEO/AUDIO 属性来实现关联分组。

Alternate Media 为 M3U8 提供外挂音频、视频、字幕的能力,可以在不改动已经存在的媒体切片的情况下,为客户端提供新的可选媒体信息。使用 EXT-X-MEDIA 中的 GROUP-ID 字段与 EXT-X-STREAM-INF 中的 AUDIO、VIDEO、SUBTITLES 关联,实现多码率、多音频、多字幕、多视角的视频播放。

10)主播放列表中的会话数据示例:

#EXT-X-SESSION-DATA:DATA-ID="com.example.lyrics",URI="lyrics.json"

#EXT-X-SESSION-DATA:DATA-ID="com.example.title",LANGUAGE="en",VALUE="This is an example"
#EXT-X-SESSION-DATA:DATA-ID="com.example.title",LANGUAGE="es",VALUE="Este es un ejemplo"

本文参考

1)M3U8 文件示例

https://developer.apple.com/library/archive/technotes/tn2288/_index.html

2)M3U8 文件标准 https://tools.ietf.org/html/rfc8216

3)HLS 协议 https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/HTTPStreamingArchitecture/HTTPStreamingArchitecture.html

通过上文的介绍,我们了解了 M3U8 媒体封装格式,这是 HLS 协议的基础,在直播和直播回放场景都有应用。我们将在后面继续探讨其他常见的媒体封装格式

猜你喜欢

转载自blog.csdn.net/yinshipin007/article/details/126374290