HLS协议中的m3u8文件格式详解:面向开发者的技术指南

什么是m3u8文件?

m3u8是HTTP Live Streaming(HLS)协议中使用的播放列表文件格式,基于UTF-8编码的m3u播放列表。m3u8文件本质上是文本文件,包含了媒体流的元数据和分段信息,使客户端能够动态适配不同带宽条件下的视频流。

基本结构解析

一个最简单的m3u8文件必须以#EXTM3U标签开头,这是m3u8文件的标识符:

#EXTM3U

主播放列表(Master Playlist)

主播放列表包含多个不同码率的流版本,让客户端能够根据网络条件自动选择最合适的流:

#EXTM3U
#EXT-X-VERSION:6

# 视频流
#EXT-X-STREAM-INF:BANDWIDTH=1500000,RESOLUTION=640x360,CODECS="avc1.42e00a,mp4a.40.2"
video_low.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=854x480,CODECS="avc1.4d401f,mp4a.40.2"
video_medium.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=4500000,RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2"
video_high.m3u8

#EXT-X-I-FRAME-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.4d401f,mp4a.40.2",BANDWIDTH=92606,AVERAGE-BANDWIDTH=47706,URI="video_high_I-Frame.m3u8"
  • #EXT-X-VERSION: 指定HLS协议版本,如果≥7,则为fmp4封装,<=6 不能确定封装形式,还需要看有没有#EXT-X-MAP

  • #EXT-X-STREAM-INF: 描述后续流的属性,包括:

    • BANDWIDTH: 带宽需求(比特/秒)
    • RESOLUTION: 分辨率
    • CODECS: 编解码器信息,常见的编码器信息有:
      • avc:h264编码
      • hvc:h265编码
      • dvc: h265 杜比视界编码
      • mp4a: 音频 aac编码,适用于音乐、播客、短视频
      • ac-3:音频 杜比数字,适用于 DVD、标清电视
      • ec-3: 音频 增强杜比,适用于蓝光、4K 流媒体、影院
  • #EXT-X-I-FRAME-STREAM-INF 该内容是 M3U8 播放列表中用于描述 关键帧(I-Frame)流信息#EXT-X-I-FRAME-STREAM-INF 标签,主要用于支持视频的快速定位、预览或缩略图生成。以下是各参数的具体含义::

    • BANDWIDTH: 带宽需求(比特/秒)

    • RESOLUTION: 分辨率

    • CODECS: 编解码器信息,常见的编码器信息有:

    • AVERAGE-BANDWIDTH=47706: 该关键帧流的平均带宽需求,单位为 bps,是播放器选择流时的参考(相比峰值更能反映整体带宽消耗)

    • URI: 指向该关键帧流的索引文件地址。这个索引文件(video_high_I-Frame.m3u8)中包含了所有关键帧的具体位置、时长等信息,播放器通过它可直接获取目标时间点的关键帧数据。

媒体播放列表(Media Playlist)

媒体播放列表包含实际媒体分段的信息:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0

#EXTINF:10.0,
segment0.ts
#EXTINF:10.0,
segment1.ts
#EXTINF:10.0,
segment2.ts
#EXT-X-ENDLIST

关键标签说明:

  • #EXT-X-TARGETDURATION: 指定每个分段的最大持续时间(秒)
  • #EXT-X-MEDIA-SEQUENCE: 播放列表中第一个分段的序列号
  • #EXTINF: 分段持续时间,后跟分段文件名
  • #EXT-X-ENDLIST: 表示播放列表不再更新(如果有,则表示是VOD点播,直播无此字段)

初始段(init segment)

为了提高效率和兼容性,支持HEVC(H265)播放,苹果公司在2017年的WWDC大会上,发布HLS 7.0(#EXT-X-VERSION=7), 开始支持基于fMP4(Fragmented MP4)的切片,fMP4是MP4格式的分片版本,每个切片都是一个独立的、可播放的MP4文件。它不仅封装开销更低,还能更好地与MPEG-DASH协议融合,后来在fmp4的基础上,进一步支持CMAF封装标准,采用CMAF标准后,内容提供商只需编码和存储一份视频文件,即可同时服务于HLS和DASH客户端,极大地节省了存储和CDN成本。

对于fMP4、CMAF容器,m3u8文件中会包含#EXT-X-MAP标签,用于指定初始化片段(init segment),这是解析fMP4的关键。

初始化段通常是一个独立的、小巧的文件,其中包含了ISO Base Media File Format(即MP4容器格式)中的 moov 原子。

示例如下:

#EXT-X-MAP:URI="init.mp4"

可以用ffprobe等工具查看其详细信息。命令如下:

ffprobe -v error -show_format -show_streams init.mp4

显示内容示例如下:

[STREAM]
index=0
codec_name=h264
codec_long_name=H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10

...
[FORMAT]
filename=init.mp4
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
...
[/FORMAT]
    • 关键信息
      • codec_name,显示编码格式:h264、H265
      • format_name字段,
        • 若为mp4mov,mp4,m4a,3gp,3g2,mj2,即为fMP4。
        • 若为mpegts,则为TS封装。

字幕轨道设置

HLS支持多种字幕格式,包括WebVTT、TTML和CEA-608/708。字幕通过在主播放列表中定义EXT-X-MEDIA标签实现:

#EXTM3U
#EXT-X-VERSION:6

# 视频流
#EXT-X-STREAM-INF:BANDWIDTH=2500000,RESOLUTION=854x480
video_medium.m3u8

# 字幕轨道 - 英文
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,
             FORCED=NO,LANGUAGE="en",URI="subtitles_en.m3u8"

# 字幕轨道 - 中文
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="中文",DEFAULT=NO,
             FORCED=NO,LANGUAGE="zh",URI="subtitles_zh.m3u8"

# 字幕轨道 - 日文
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="日本語",DEFAULT=NO,
             FORCED=NO,LANGUAGE="ja",URI="subtitles_ja.m3u8"

字幕播放列表示例(WebVTT格式):

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD

# 指定WebVTT格式
#EXT-X-SUBTITLES-FORMAT:WEBVTT
#EXT-X-SUBTITLES-LANGUAGE:en

#EXTINF:10.000,
subtitle0.vtt
#EXTINF:10.000,
subtitle1.vtt
#EXTINF:10.000,
subtitle2.vtt
#EXT-X-ENDLIST

章节设置

在 M3U8(HLS 协议)中,对“章节”(Chapter)的支持主要通过 #EXT-X-CHAPTER 系列标签实现,用于将视频内容划分为多个逻辑章节(如片头、正片分幕、片尾等),方便播放器展示章节列表、快速跳转。这些标签在 HLS 协议 版本 8 及以上EXT-X-VERSION:8+)中定义。

一、章节相关核心标签

标签 作用
#EXT-X-CHAPTER 标记一个章节的开始,需配合 URITIME-OFFSET 定义章节位置
#EXT-X-CHAPTER-ID 为章节指定唯一 ID(可选,用于标识章节)
#EXT-X-CHAPTER-DURATION 定义章节的持续时间(可选,单位:秒,精确到小数点后 9 位)
#EXT-X-CHAPTER-TITLE 定义章节的标题(可选,用于播放器显示,支持 UTF-8 字符)
#EXT-X-CHAPTER-URI 指向章节对应的媒体片段(可选,若章节对应独立的媒体流)
#EXT-X-CHAPTER-TIME-OFFSET 定义章节在主媒体流中的起始时间偏移(相对于流的起始点,单位:秒)

二、章节支持的两种场景及示例

场景 1:章节为同一媒体流中的时间片段(最常用)

章节基于主媒体流的时间轴划分,无需额外媒体文件,仅通过 TIME-OFFSET 定义起始位置。

#EXTM3U
#EXT-X-VERSION:8  # 必须使用版本 8 及以上
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0

# 章节 1:片头(从 0 秒开始,持续 30 秒)
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:chapter1
#EXT-X-CHAPTER-TITLE:片头
#EXT-X-CHAPTER-TIME-OFFSET:0.0
#EXT-X-CHAPTER-DURATION:30.0

# 章节 2:正片第一幕(从 30 秒开始,持续 120 秒)
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:chapter2
#EXT-X-CHAPTER-TITLE:正片 - 第一幕
#EXT-X-CHAPTER-TIME-OFFSET:30.0
#EXT-X-CHAPTER-DURATION:120.0

# 章节 3:片尾(从 150 秒开始,持续 20 秒)
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:chapter3
#EXT-X-CHAPTER-TITLE:片尾
#EXT-X-CHAPTER-TIME-OFFSET:150.0
#EXT-X-CHAPTER-DURATION:20.0

# 主媒体流片段(覆盖所有章节的时间范围)
#EXTINF:10.0,
segment_0.ts
#EXTINF:10.0,
segment_1.ts
#EXTINF:10.0,
segment_2.ts
#EXTINF:10.0,
segment_3.ts
#EXTINF:10.0,
segment_4.ts
#EXTINF:10.0,
segment_5.ts
#EXTINF:10.0,
segment_6.ts
#EXTINF:10.0,
segment_7.ts
#EXTINF:10.0,
segment_8.ts
#EXTINF:10.0,
segment_9.ts

#EXT-X-ENDLIST

场景 2:章节对应独立的媒体流(较少用)

章节通过 URI 指向独立的媒体片段文件,适用于章节内容分离的场景(如多章节分别编码)。

#EXTM3U
#EXT-X-VERSION:8
#EXT-X-TARGETDURATION:10

# 章节 1:独立片头媒体流
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:intro
#EXT-X-CHAPTER-TITLE:片头
#EXT-X-CHAPTER-URI:chapters/intro.m3u8  # 指向片头的子 M3U8
#EXT-X-CHAPTER-DURATION:30.0

# 章节 2:独立正片媒体流
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:main
#EXT-X-CHAPTER-TITLE:正片
#EXT-X-CHAPTER-URI:chapters/main.m3u8   # 指向正片的子 M3U8
#EXT-X-CHAPTER-DURATION:600.0

# 章节 3:独立片尾媒体流
#EXT-X-CHAPTER
#EXT-X-CHAPTER-ID:outro
#EXT-X-CHAPTER-TITLE:片尾
#EXT-X-CHAPTER-URI:chapters/outro.m3u8  # 指向片尾的子 M3U8
#EXT-X-CHAPTER-DURATION:20.0

#EXT-X-ENDLIST

三、关键说明

  1. 版本要求:必须在 EXT-X-VERSION:8 及以上版本中使用,低版本不支持章节标签。
  2. 播放器兼容性:并非所有 HLS 播放器都支持章节显示(如部分老旧播放器可能忽略章节标签),主流播放器(如 Safari、VLC、ExoPlayer 最新版)通常支持。
  3. 标签顺序:章节标签需放在媒体片段列表之前(#EXTINF 之前),确保播放器先解析章节信息。
  4. 时间精度TIME-OFFSETDURATION 支持小数点后 9 位,可精确到纳秒级,适应高帧率视频。

通过章节标签,可实现类似本地视频播放器的“章节导航”功能,提升长视频(如电影、课程)的交互体验。

标记广告插播时段设置

广告插入标准 SCTE-35 在 HLS 中的映射。它们的核心作用是定义 “主内容中断(插入广告)” 和 “广告结束(恢复主内容)” 的时间点

以下两个标签源自对 SCTE-35 信号(广电领域的广告插入控制信号)的支持,主要用于流媒体中的动态广告插入(DAI),具体逻辑:

  • #EXT-X-CUE-OUT:<duration>:标记主内容在此处中断,开始插入广告,duration 是预计的广告总时长(秒)。
  • #EXT-X-CUE-IN:标记广告插入结束,恢复主内容播放。

示例如下:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10

# 主内容片段
#EXTINF:10.0,
main_0.ts
#EXTINF:10.0,
main_1.ts

# 标记主内容中断,插入15秒广告
#EXT-X-CUE-OUT:15.0
#EXTINF:5.0,
ad_0.ts  # 广告片段1
#EXTINF:5.0,
ad_1.ts  # 广告片段2
#EXTINF:5.0,
ad_2.ts  # 广告片段3

# 标记广告结束,恢复主内容
#EXT-X-CUE-IN
#EXTINF:10.0,
main_2.ts
#EXTINF:10.0,
main_3.ts

#EXT-X-ENDLIST

直播流与点播流

点播流包含#EXT-X-ENDLIST标签,表示完整的播放列表:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
...
#EXT-X-ENDLIST

直播流不包含结束标签,且需要客户端定期刷新获取新分段:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:2680

#EXTINF:10.0,
segment2680.ts
#EXTINF:10.0,
segment2681.ts

加密与DRM

m3u8支持媒体加密,提供基础的内容保护:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-KEY:METHOD=AES-128,URI="key.php",IV=0x9c7db8778570d05c2a4d7d5a7f5c8d9c
#EXTINF:10.0,
segment0.ts

加密相关标签:

  • METHOD: 加密方法(NONE, AES-128, SAMPLE-AES)
  • URI: 密钥获取地址
  • IV: 初始化向量(可选)

高级功能

分段字节范围访问

允许单个文件包含多个分段,节省请求开销:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-BYTERANGE:82112@0

#EXTINF:10.0,
video.ts
#EXT-X-BYTERANGE:83232@82112
#EXTINF:10.0,
video.ts

实际应用:生成带字幕和广告的m3u8文件

以下是一个简单的Node.js示例,演示如何生成包含字幕和广告信息的m3u8文件:

function generateMasterPlaylist(videoStreams, subtitles) {
  let m3u8 = '#EXTM3U\n';
  m3u8 += '#EXT-X-VERSION:6\n';
  
  // 添加视频流
  videoStreams.forEach(stream => {
    m3u8 += `#EXT-X-STREAM-INF:BANDWIDTH=${stream.bandwidth},RESOLUTION=${stream.resolution}\n`;
    m3u8 += `${stream.uri}\n`;
  });
  
  // 添加字幕轨道
  subtitles.forEach(sub => {
    m3u8 += `#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="${sub.name}",DEFAULT=${sub.default ? 'YES' : 'NO'},LANGUAGE="${sub.language}",URI="${sub.uri}"\n`;
  });
  
  return m3u8;
}

function generateMediaPlaylistWithChapters(segments, chapters) {
  let m3u8 = '#EXTM3U\n';
  m3u8 += '#EXT-X-VERSION:6\n';
  m3u8 += `#EXT-X-TARGETDURATION:${segments[0].duration}\n`;
  m3u8 += `#EXT-X-MEDIA-SEQUENCE:0\n`;
  
  let currentTime = 0;
  let chapterIndex = 0;
  
  segments.forEach((segment, index) => {
    // 检查是否需要添加广告标记
    if (adIndex < ads.length && 
        currentTime >= ads[adIndex].startTime) {
      m3u8 += `#EXT-X-CUE-OUT:${ads[adIndex].duration}\n`;
      adIndex++;
    }
    
    m3u8 += `#EXTINF:${segment.duration},\n`;
    m3u8 += `${segment.uri}\n`;
    
    currentTime += segment.duration;
  });
  
  m3u8 += '#EXT-X-ENDLIST\n';
  return m3u8;
}

调试与验证

开发者可以使用以下工具验证m3u8文件:

  1. FFmpeg:

    ffmpeg -i input.m3u8 -c copy output.mp4
  2. hls.js: Web端的HLS客户端库,适合调试播放问题

  3. Apple的mediastreamvalidator: 官方验证工具

  4. VLC媒体播放器: 支持播放HLS流并显示字幕和章节信息

最佳实践

  1. 分段时长建议设置在6-10秒之间
  2. 确保#EXT-X-TARGETDURATION等于或略大于实际最长分段
  3. 对于直播流,保持播放列表长度适中(通常包含4-6个最近分段)
  4. 使用CDN加速分段文件分发
  5. 考虑启用Gzip压缩减少m3u8文件大小
  6. 为字幕提供多语言支持,并设置合适的DEFAULT轨道
  7. 章节标记应该精确对齐I帧,避免播放器跳转不准确

常见问题排查

  1. 播放失败: 检查m3u8文件路径和分段文件可访问性
  2. 卡顿: 检查分段时长是否一致,网络带宽是否足够
  3. 加密问题: 确认密钥服务器可访问且返回正确格式的密钥
  4. 字幕不显示: 检查字幕文件格式和MIME类型设置
  5. 章节标记不准: 确保章节开始时间与关键帧对齐

实例解析说明

下面以一个实例来说明,地址为: https://d2zihajmogu5jn.cloudfront.net/elephantsdream/hls/ed_hd.m3u8

内容如下:

#EXTM3U

#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="en",CHARACTERISTICS="public.accessibility.transcribes-spoken-dialog,public.accessibility.describes-music-and-sound",URI="manifest9/captions.en.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Swedish",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="sv",URI="manifest10/captions.sv.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Russian",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="ru",URI="manifest11/captions.ru.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Japanese",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="ja",URI="manifest12/captions.ja.m3u8"
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Arabic",DEFAULT=NO,AUTOSELECT=YES,FORCED=NO,LANGUAGE="ar",URI="manifest13/captions.ar.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="ed_audio_64k",LANGUAGE="en",NAME="Main",CHANNELS="2",AUTOSELECT=YES,DEFAULT=YES,URI="manifest5/index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="ed_audio_64k",LANGUAGE="en",NAME="Audio Described",CHANNELS="2",AUTOSELECT=YES,DEFAULT=NO,CHARACTERISTICS="public.accessibility.describes-video",URI="manifest6/index.m3u8"

#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="ed_audio_128k",LANGUAGE="en",NAME="Main",CHANNELS="2",AUTOSELECT=YES,DEFAULT=YES,URI="manifest7/index.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="ed_audio_128k",LANGUAGE="en",NAME="Audio Described",CHANNELS="2",AUTOSELECT=YES,DEFAULT=NO,CHARACTERISTICS="public.accessibility.describes-video",URI="manifest8/index.m3u8"


#EXT-X-STREAM-INF:BANDWIDTH=2100000,AVERAGE-BANDWIDTH=800000,CODECS="mp4a.40.2, avc1.4d001e",RESOLUTION=480x270,FRAME-RATE=24,AUDIO="ed_audio_64k",SUBTITLES="subs"
manifest0/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=3300000,AVERAGE-BANDWIDTH=1050000,CODECS="mp4a.40.2, avc1.4d001f",RESOLUTION=640x360,FRAME-RATE=24,AUDIO="ed_audio_64k",SUBTITLES="subs"
manifest1/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=6000000,AVERAGE-BANDWIDTH=2000000,CODECS="mp4a.40.2, avc1.4d0028",RESOLUTION=854x480,FRAME-RATE=24,AUDIO="ed_audio_64k",SUBTITLES="subs"
manifest2/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=10000000,AVERAGE-BANDWIDTH=3000000,CODECS="mp4a.40.2, avc1.640028",RESOLUTION=1280x720,FRAME-RATE=24,AUDIO="ed_audio_128k",SUBTITLES="subs"
manifest3/index.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=21000000,AVERAGE-BANDWIDTH=6000000,CODECS="mp4a.40.2, avc1.64002a",RESOLUTION=1920x1080,FRAME-RATE=24,AUDIO="ed_audio_128k",SUBTITLES="subs"
manifest4/index.m3u8

这是一个非常典型且功能完整的HLS主播放列表(Master Playlist)。它定义了一个包含多码率视频流、多语言字幕和多版本音轨的复杂媒体演示。

下面将为您逐部分详细说明其内容:

文件类型

  • #EXTM3U: 表明这是一个M3U播放列表文件。

第一部分:字幕轨道定义 (#EXT-X-MEDIA:TYPE=SUBTITLES)

这部分定义了5种不同语言的字幕轨道,它们都属于同一个组 GROUP-ID="subs"

  1. 英语字幕 (English)

    • TYPE=SUBTITLES: 媒体类型为字幕。
    • GROUP-ID="subs": 组标识符,视频流会引用这个ID来关联字幕。
    • NAME="English": 显示给用户看的名称。
    • DEFAULT=YES: 默认选择。播放器首次加载时会自动加载此字幕轨道。
    • AUTOSELECT=YES: 如果播放器设置的语言与用户偏好匹配,会自动选择此轨道。
    • FORCED=NO: 这不是强制字幕(如只包含背景音翻译的字幕)。
    • LANGUAGE="en": 语言代码。
    • CHARACTERISTICS="...": 描述了该字幕的特性(可转录对话、描述音乐和音效),这是一个辅助功能特性。
    • URI="manifest9/captions.en.m3u8": 指向包含实际字幕片段(如WebVTT文件)的播放列表。
  2. 瑞典语、俄语、日语、阿拉伯语字幕

    • 参数与英语字幕类似,但 DEFAULT=NO(非默认),并且没有 CHARACTERISTICS 属性。
    • 它们各自有对应的语言代码和专属的播放列表URI。

小结:用户可以在播放器中从5种语言(英、瑞典、俄、日、阿拉伯)中选择字幕,其中英语是默认选项。


第二部分:音轨定义 (#EXT-X-MEDIA:TYPE=AUDIO)

这部分定义了两组不同比特率的音频轨道,每组都包含两个版本:主音轨和音频描述音轨。

第一组:64kbps 音频组 (GROUP-ID="ed_audio_64k")

  1. 主音轨 (Main)

    • TYPE=AUDIO: 媒体类型为音频。
    • GROUP-ID="ed_audio_64k": 组标识符。
    • LANGUAGE="en": 英语。
    • NAME="Main": 名称是“主音轨”。
    • CHANNELS="2": 双声道立体声。
    • DEFAULT=YES: 该组中的默认选择。
    • URI="manifest5/index.m3u8": 指向64kbps主音轨的播放列表。
  2. 音频描述音轨 (Audio Described)

    • NAME="Audio Described": 这是为视障用户提供的音频描述版本,会在视频对话的间隙描述场景、动作和表情。
    • CHARACTERISTICS="public.accessibility.describes-video": 明确指出了其辅助功能特性。
    • DEFAULT=NO: 非默认选项。
    • 其他属性与主音轨相同。

第二组:128kbps 音频组 (GROUP-ID="ed_audio_128k")

  • 结构与第一组完全相同,但比特率更高(理论上音质更好),对应的播放列表URI也不同(manifest7/manifest8/)。

小结:提供了两种音质的音频(64kbps和128kbps),每种音质下用户都可以选择听标准主音轨或带有画面描述的辅助音轨。


第三部分:视频流定义 (#EXT-X-STREAM-INF)

这部分定义了5个不同码率和分辨率的视频流。播放器会根据当前的网络带宽自动选择最合适的一个进行播放。所有视频流都不包含音频(音频通过后面的AUDIO属性关联)。

  1. 270p 低码率流

    • BANDWIDTH=2100000: 峰值带宽约为2.1 Mbps。
    • AVERAGE-BANDWIDTH=800000: 平均带宽约为0.8 Mbps。
    • CODECS="mp4a.40.2, avc1.4d001e": 指定编解码器。
      • mp4a.40.2: AAC-LC 音频编解码器(但此视频流不含音频,此编解码信息指的是它需要关联的音频流的格式)。
      • avc1.4d001e: H.264 视频编解码器 profile 和 level,对应标清分辨率。
    • RESOLUTION=480x270: 分辨率 480x270 (270p)。
    • FRAME-RATE=24: 帧率 24 fps。
    • AUDIO="ed_audio_64k": 关联音频组。选择此视频流时,播放器会去加载 GROUP-ID="ed_audio_64k" 的音频。
    • SUBTITLES="subs": 关联字幕组。表示可用的字幕轨道是 GROUP-ID="subs" 的那一组。
    • manifest0/index.m3u8: 指向该码流对应的媒体播放列表文件。
  2. 360p, 480p, 720p, 1080p 流

    • 后续四个流的参数模式类似:码率、分辨率、视频编解码等级(avc1.4d001f -> avc1.64002a)逐渐提升,以提供更高质量的视频。
    • 关键区别:前三个较低码率的流(270p, 360p, 480p)关联的是 ed_audio_64k 音频组,而更高码率的两个流(720p, 1080p)关联的是 ed_audio_128k 音频组。这是一种优化策略,为高清视频搭配更高质量的音频。

工作流程

  1. 播放器加载:播放器首先加载这个主播放列表文件。
  2. 获取可用选项:解析列表,获知有5个视频码率、2种音质(每组2个版本)、5种字幕可供选择。
  3. 自适应选择
    • 播放器根据当前网络带宽,从5个视频流中选择一个最合适的(例如,网速好则选择 manifest4/index.m3u8 的1080p流)。
    • 根据用户设置或默认值,选择对应的音轨(例如 ed_audio_128k 组里的「Main」音轨)和字幕(例如「English」)。
  4. 并行加载:播放器同时加载选择好的视频流媒体列表、音频流媒体列表和字幕媒体列表,然后下载相应的音视频及字幕片段进行同步播放。
  5. 动态切换:如果网络条件发生变化,播放器会自动在不同码率的视频流之间无缝切换。

这个m3u8文件体现了一个非常专业和用户友好的流媒体配置,充分考虑到了不同网络条件下的体验、多语言用户以及视障人士的辅助功能需求。

结语

m3u8作为HLS协议的核心,提供了强大的自适应流媒体能力,包括丰富的字幕和章节支持。理解其文件格式和各项标签的含义,对于开发流媒体应用至关重要。随着HLS技术的不断发展,建议开发者持续关注新的标签和功能,以提供更优质的流媒体体验。

通过本文的介绍,您应该对m3u8文件格式有了全面的了解,能够创建、解析和调试包含字幕和章节的HLS流媒体播放列表。

zwplayer播放器是为数不多的支持m3u8格式多码率自适应播放、内嵌字幕播放的播放器,欢迎大家使用😀