当前位置:首页 >> 技术博客 >> 视频技术

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

时间:2025-09-16 访问量:4
目录导航

    什么是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-VERSION: 指定HLS协议版本

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

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

      • RESOLUTION: 分辨率

      • CODECS: 编解码器信息

    媒体播放列表(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内容)

    字幕轨道设置

    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

    章节标记设置

    HLS支持通过EXT-X-CUE-OUTEXT-X-CUE-IN等标签实现章节标记:

    #EXTM3U
    #EXT-X-VERSION:6
    #EXT-X-TARGETDURATION:10
    #EXT-X-MEDIA-SEQUENCE:0
    
    # 第一章开始 (持续30秒)
    #EXT-X-CUE-OUT:30
    #EXTINF:10.0,
    segment0.ts
    #EXTINF:10.0,
    segment1.ts
    #EXTINF:10.0,
    segment2.ts
    # 第一章结束
    #EXT-X-CUE-IN
    #EXTINF:10.0,
    segment3.ts
    
    # 第二章开始 (持续20秒)
    #EXT-X-CUE-OUT:20
    #EXTINF:10.0,
    segment4.ts
    #EXTINF:10.0,
    segment5.ts
    # 第二章结束
    #EXT-X-CUE-IN
    #EXTINF:10.0,
    segment6.ts

    对于更丰富的章节元数据,可以使用EXT-X-DATERANGE标签:

    #EXTM3U
    #EXT-X-VERSION:6
    
    # 第一章
    #EXT-X-DATERANGE:ID="chapter1",START-DATE="2023-01-01T00:00:00Z",
                     DURATION=30.0,X-CHAPTER-TITLE="Introduction"
    #EXTINF:10.0,
    segment0.ts
    
    # 第二章
    #EXT-X-DATERANGE:ID="chapter2",START-DATE="2023-01-01T00:00:30Z",
                     DURATION=20.0,X-CHAPTER-TITLE="Main Content"
    #EXTINF:10.0,
    segment1.ts

    直播流与点播流

    点播流包含#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

    时间戳映射

    对于MP4容器格式,提供时间映射信息:

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

    实际应用:生成带字幕和章节的m3u8文件

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

    function generateMasterPlaylist(videoStreams, subtitles) {
      let m3u8 = '#EXTM3U
    ';
      m3u8 += '#EXT-X-VERSION:6
    ';
      
      // 添加视频流
      videoStreams.forEach(stream => {
        m3u8 += `#EXT-X-STREAM-INF:BANDWIDTH=${stream.bandwidth},RESOLUTION=${stream.resolution}
    `;
        m3u8 += `${stream.uri}
    `;
      });
      
      // 添加字幕轨道
      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}"
    `;
      });
      
      return m3u8;
    }
    
    function generateMediaPlaylistWithChapters(segments, chapters) {
      let m3u8 = '#EXTM3U
    ';
      m3u8 += '#EXT-X-VERSION:6
    ';
      m3u8 += `#EXT-X-TARGETDURATION:${segments[0].duration}
    `;
      m3u8 += `#EXT-X-MEDIA-SEQUENCE:0
    `;
      
      let currentTime = 0;
      let chapterIndex = 0;
      
      segments.forEach((segment, index) => {
        // 检查是否需要添加章节标记
        if (chapterIndex < chapters.length && 
            currentTime >= chapters[chapterIndex].startTime) {
          m3u8 += `#EXT-X-CUE-OUT:${chapters[chapterIndex].duration}
    `;
          chapterIndex++;
        }
        
        m3u8 += `#EXTINF:${segment.duration},
    `;
        m3u8 += `${segment.uri}
    `;
        
        currentTime += segment.duration;
      });
      
      m3u8 += '#EXT-X-ENDLIST
    ';
      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 低码率流

      • mp4a.40.2: AAC-LC 音频编解码器(但此视频流不含音频,此编解码信息指的是它需要关联的音频流的格式)。

      • avc1.4d001e: H.264 视频编解码器 profile 和 level,对应标清分辨率。

      • BANDWIDTH=2100000: 峰值带宽约为2.1 Mbps。

      • AVERAGE-BANDWIDTH=800000: 平均带宽约为0.8 Mbps。

      • CODECS="mp4a.40.2, avc1.4d001e": 指定编解码器。

      • 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格式多码率自适应播放、内嵌字幕播放的播放器,欢迎大家使用😀

    电话交流
    加微信