当前位置: 首页 > java >正文

一文详解 HLS

1 HLS的简介

1.1 HLS的背景

RTMP(Real-Time Messaging Protocol,实时消息传输协议)HLS(HTTP Live Streaming,HTTP直播流) 的技术演进,本质上是直播协议从 专有协议通用 Web 协议 的转变,也是适应互联网环境(如浏览器支持、移动端普及)的必然结果。

1. RTMP的核心问题

  • 依赖Flash Player:RTMP是Adobe开发的专有协议,长期依赖Flash插件实现浏览器播放。但Flash存在安全漏洞多、移动端支持差(如早期iOS不支持)等问题,逐渐被淘汰。
  • 防火墙与跨平台限制:RTMP通常使用非标准端口(如1935),容易被防火墙拦截;且无法直接在HTML5中播放,需插件支持。
  • 实时性与灵活性的矛盾:RTMP虽实时性强(延迟约1-3秒),但封装格式(FLV)和传输方式难以适应动态网络环境(如弱网、带宽波动)。

2. HLS的设计目标

  • 基于HTTP协议:利用HTTP的广泛兼容性(浏览器原生支持)和防火墙友好性,无需额外插件即可播放。
  • 分段传输(Chunked Transfer):将直播流分割为小尺寸的媒体片段(如TS/MP4文件),支持动态调整码率,适应不同网络条件。
  • 无状态协议:HTTP的无状态特性使服务器架构更简单,易于扩展(如CDN分发),降低直播成本。

HLS的核心问题

HLS 的延迟问题确实是其最被诟病的缺点之一,实际应用中延迟通常在 5-30 秒 之间(不同场景差异较大),极端情况下可能更高。这一现象是由其 设计机制 和 网络传输特性 共同决定的 后面解释

1.2 HLS的工作原理

在这里插入图片描述

  • 音视频采集
    摄像机等设备获取原始的音频和视频信号 ,这些信号是未经处理的模拟或数字信号。比如摄像机捕捉现场画面,麦克风收录现场声音。
  • 媒体编码
    • 位置与作用:采集到的音视频输入到服务器中的媒体编码器(Media encoder )。媒体编码器会按照特定的编码标准,如视频常用的 H.264、H.265,音频常用的 AAC 等 ,对原始音视频数据进行压缩编码。这一步是为了减小数据量,便于后续的传输和存储 。
    • 编码原理:以 H.264 为例,它利用帧间预测、变换编码等技术,去除视频中的冗余信息 。比如对于连续的相似帧,只记录关键帧和帧间差异,大幅降低数据量。
  • 流分段
    • 处理过程:编码后的音视频数据形成 MPEG - 2 传输流,进入流分段器(Stream segmenter )。流分段器将连续的媒体流切割成一个个小的片段,通常这些片段是.ts(MPEG - 2 传输流格式)格式 ,每个片段时长一般为几秒到十几秒 。例如设置每个片段时长为 5 秒,流分段器就会按时间间隔把流切割成相应的小段。
    • 目的:分段是 HLS 的关键特性,便于客户端按顺序下载播放,也利于实现码率自适应等功能 。
  • 分发准备
    • 索引文件生成:源 Web 服务器(Origin web server )会生成一个索引文件(Index file ,通常是.m3u8 格式 )。索引文件记录了各个媒体片段的信息,包括片段的 URL 地址、时长等 。比如索引文件会明确指出第一个.ts 片段的地址在哪,第二个片段地址在哪等。
    • 文件存储:服务器将生成的媒体片段(.ts 文件 )和索引文件存储好,等待客户端请求 。
  • 网络传输
    最终通过 HTTP 协议,服务器将索引文件和媒体片段传输给客户端 。客户端通过解析索引文件,按顺序下载媒体片段进行播放 。

2 HLS 基本框架

在这里插入图片描述
服务器

  • 复用与封装
    编码后的音视频基本流,会被复用并封装成符合 MPEG - 2 系统层标准的传输流(TS)格式。MPEG - 2 TS 格式能将音视频媒体流严格按时序交织复用 。这样,任意截取和分段后的每个小段,都可独立解码和播放**。每个 TS 文件开头需包含节目关联表(PAT)和节目映射表(PMT) ;含视频的文件,还得有至少一个关键帧及序列头等信息,用于解码器初始化**。
  • 流分割处理
    流分割器(Stream Segmenter)会将编码器输出的 MPEG - 2 TS 流,分割成一系列连续且长度均等的小 TS 文件(后缀为.ts )。同时,流分割器会创建一个索引文件(采用扩展的 M3U 播放列表格式,后缀名.m3u8 ) ,该文件包含指向小 TS 文件的指针。索引文件类似播放列表滑动窗口,每当生成新 TS 文件,其内容就会更新 ,新文件 URI 添加到末尾,旧的被移除,始终保持固定数量的最新分段信息。此外,流分割器还可对小 TS 文件加密,并生成密钥文件。
    在这里插入图片描述

之所以采用 MPEG - 2 TS 格式统一封装编码后的媒体流,**是因其具备让各分段独立解码播放的特性。M3U8 索引文件是由若干文本行组成的文本文件 ,每行可能是 URI、**空行或以注释符 “#” 起始的行 。其中,URI 指向分段媒体文件或衍生索引文件;以 “#EXT” 起始的行是标签行,其他 “#” 起始行是可忽略的注释。以下是一个简单.m3u8 索引文件示例,其表示的媒体流由 5 个时长 5秒的未加密 TS 文件构成。


#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:54
#EXT-X-TARGETDURATION:6
#EXTINF:5.000, no desc
livestream-54.ts
#EXTINF:5.000, no desc
livestream-55.ts
#EXTINF:5.002, no desc
livestream-56.ts
#EXTINF:5.018, no desc
livestream-57.ts
#EXTINF:5.982, no desc
livestream-58.ts

内容分发

HLS 内容分发系统通过 HTTP 协议传输分割后的媒体文件(.ts)和索引文件(.m3u8),可直接使用普通 Web 服务器或 CDN,无需特殊配置,仅需关联 MIME 类型:

.m3u8 → application/vnd.apple.mpegurl
.ts → video/MP2T

关键优化:

.m3u8 文件:设短缓存时间(如 5-10 秒),避免客户端获取旧索引,确保实时性。
.ts 文件:设长缓存时间(如 24 小时),减少重复下载,提升效率。

通过 CDN 加速和合理缓存策略,可高效分发内容,平衡实时性与带宽成本。

客户端

  • 获取索引文件(.m3u8)
    客户端通过网页 URL 请求服务器获取 HLS 索引文件,文件中包含:
    当前可用的 TS 媒体片段 URL 列表
    解密密钥地址(若加密)
    多码率替换流索引(可选)
  • 下载与缓冲媒体片段
    按索引顺序下载 TS 文件,至少缓冲 1-2 个片段 后开始播放(推荐 2 个以保证无缝衔接)。(这无疑是延时的重要原因)
    直播场景中,客户端周期性刷新索引文件,获取最新片段 URL 并添加到下载队列。
    点播场景中,遇 #EXT-X-ENDLIST 标签则结束播放。
  • 解码与播放
    拼装 TS 片段为完整流,送播放器解码。
    加密流需通过索引获取密钥,完成用户认证和解密。

⽹络⾃适应的流间切换和故障保护

  1. 多码率流的预先生成
    服务器端对同一音视频源进行不同码率的编码(如 240P/360P/720P/1080P 等),生成多套 TS 媒体片段(每个码率对应独立的 TS 片段序列)。
    为每套码率流生成独立的索引文件(.m3u8),记录该码率下 TS 片段的 URL、时长等信息。
** 主索引文件(Master Playlist)** 中包含所有码率流的索引文件地址,格式如下:
plaintext
#EXTM3U
#EXT-X-STREAM-INF:BANDWIDTH=500000,RESOLUTION=854x480  # 低码率流
http://example.com/low.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720 # 高码率流
http://example.com/high.m3u8
  1. 客户端动态切换逻辑
    实时监测网络带宽:通过下载速度、缓冲状态、RTT(往返时间)等指标估算当前可用带宽。
    比较带宽与码率阈值:若当前带宽低于某码率的最低要求(如 720P 需至少 2Mbps),则切换至更低码率;若带宽充足,则切换至更高码率以提升画质。
    平滑过渡机制:切换时等待当前片段播放完毕,再从新码率的下一个片段开始加载,避免画面中断。

HLS(HTTP Live Streaming)被称为 “以点播形式实现直播”,核心在于其技术实现逻辑完全基于HTTP 协议的文件分块下载机制,而非传统直播协议的实时数据流传输

  • 传统直播与HLS的本质区别
对比维度传统直播协议(如RTMP/RTSP)HLS
数据传输形式基于TCP/UDP的实时数据流,服务器持续推送数据。基于HTTP的文件分块下载,数据封装为独立TS文件。
客户端获取方式直接接收连续数据流,边收边解。主动下载分段文件(TS片段),拼装后播放。
服务器角色实时生成数据流并推送。提前生成或实时切割TS文件,供客户端拉取。
  • 为什么说HLS的“直播是点播的变种”?
  1. 无实时数据流,只有文件序列
  • 传统直播协议中,服务器与客户端建立长连接,数据流如“水管放水”般连续传输。
  • HLS中,服务器仅提供文件列表文件资源,客户端通过“下载文件序列”模拟直播,本质是点播技术的时序化应用
  1. 延迟来源于文件分块和缓冲
  • 直播延迟的核心原因:
    • 文件分块时长:每个TS文件至少5秒,服务器生成新文件需要时间。
    • 缓冲机制:客户端需下载并缓冲多个片段(如2个10秒片段)才能开始播放。
  • 对比传统直播:RTMP协议延迟可低至1-3秒,而HLS典型延迟为20-30秒(因需等待文件生成和下载)。

3 m3u8协议

示例1:单码率媒体流索引

#EXTM3U                          # M3U8文件标识(必填)
#EXT-X-VERSION:3                  # 协议版本号(如3)
#EXT-X-ALLOW-CACHE:YES            # 允许缓存(YES/NO)
#EXT-X-MEDIA-SEQUENCE:2           # 起始媒体段序列号(从2开始)
#EXT-X-TARGETDURATION:16          # 单个TS片段最大时长(秒),需≥所有#EXTINF值
#EXTINF:14.357, no desc           # 片段时长(秒)+描述(可选)
livestream-2.ts                   # 媒体段URI(对应TS文件)
#EXTINF:15.617, no desc
livestream-3.ts
#EXTINF:14.358, no desc
livestream-4.ts
  • 特点:直接列出TS文件URI,用于单一码率的直播或点播流。

示例2:多码率适配流索引(主索引文件)

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000  # 子流带宽(必填)
http://example.com/low.m3u8                        # 低码率子索引URI
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000
http://example.com/mid.m3u8                        # 中码率子索引URI
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,RESOLUTION=1080x720
http://example.com/hi.m3u8                         # 高码率子索引URI(含分辨率)
  • 特点:通过#EXT-X-STREAM-INF标签嵌套子M3U8文件,每个子索引对应不同码率流,客户端根据带宽动态选择。

** M3U8核心标签解析**
M3U8是纯文本文件,由标签(Tag)URI注释组成,以#开头的行为标签或注释,其余为URI或空行。以下是关键标签:

标签说明必填性示例
#EXTM3U文件头,标识为M3U8格式(必填)第一行固定为此标签
#EXT-X-VERSION协议版本号(如3/4),影响标签兼容性(如#EXT-X-BYTERANGE需版本≥4)#EXT-X-VERSION:3
#EXTINF定义后续URI对应的TS片段时长(秒)和描述(可选)是(单码率)#EXTINF:10.0, Live segment 1
#EXT-X-TARGETDURATION最大片段时长(秒),需≥所有#EXTINF值,全局唯一是(单码率)#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE媒体段序列号,后续片段依次递增(默认从0开始)#EXT-X-MEDIA-SEQUENCE:1
#EXT-X-KEY加密配置(NONE/AES-128),指定密钥URI和初始化向量(IV)#EXT-X-KEY:METHOD=AES-128,URI=“key.bin”,IV=0x1234…
#EXT-X-STREAM-INF多码率场景下,定义子索引文件的带宽、分辨率等属性(嵌套子M3U8时必填)是(多码率)#EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1080x720
#EXT-X-ENDLIST标识点播流结束(直播流无此标签)否(点播)#EXT-X-ENDLIST

** 关键机制说明**

  1. 单码率与多码率切换

    • 单码率:客户端直接下载TS片段,适用于固定网络环境。
    • 多码率
      • 主索引文件列出各码率子索引(含带宽、分辨率等信息)。
      • 客户端根据实时带宽选择子索引,如带宽不足2Mbps时自动切换至low.m3u8
  2. 缓存与更新策略

    • #EXT-X-ALLOW-CACHE:NO:禁止缓存M3U8文件,确保客户端每次获取最新索引(适用于直播)。
    • 浏览器对M3U8的缓存由HTTP头(如Cache-Control)控制,建议设置短缓存时间(如5秒)。
  3. 加密与解密

    • 通过#EXT-X-KEY标签启用AES-128加密:
      • METHOD=NONE:不加密(默认)。
      • METHOD=AES-128:需指定密钥文件URI(如http://example.com/key.bin),IV可选(缺省则用序列号生成)。

** 直播与点播场景差异**

场景关键特征标签差异
直播索引文件动态更新,持续追加新TS片段URI,无结束标签#EXT-X-ENDLIST,需定期刷新索引
点播索引文件固定,包含完整TS列表,末尾需#EXT-X-ENDLIST标识结束包含#EXT-X-ENDLIST,无需刷新索引

2.5 嵌套层级限制

  • M3U8仅支持一层嵌套:主索引文件(多码率)嵌套子索引文件(单码率),子索引文件直接指向TS片段。
  • 禁止多层嵌套(如主索引→子索引→孙索引),避免解析复杂度过高。

总结
M3U8文件通过标准化标签体系实现了对TS片段的有序管理,其核心价值在于:

  • 单码率场景:提供简单、可靠的片段索引。
  • 多码率场景:结合客户端带宽自适应,保障不同网络下的播放体验。
  • 扩展性:通过标签支持加密、时间同步、多语言轨道等高级功能。

4 ts协议解析

4.1 基本框架

TS(Transport Stream,传输流)文件的分层结构设计精巧,由下至上可分为三层,这种分层模式使得音视频数据在传输过程中更高效、稳定,各层各司其职,协同保障数据准确无误地流转与处理。
在这里插入图片描述

  • ES 层(Elementary Stream,基本码流层):这是最底层,处于音视频数据的初始状态,即经过压缩编码后的原始音视频数据。视频编码多采用 H.264、H.265 等格式,音频编码常用 AAC、MP3 等格式。在这一层,数据以连续码流形式存在,一个 ES 流仅包含单一类型数据,如纯视频、纯音频或纯字幕。例如,一个 H.264 编码的视频 ES 流,其中全是按照 H.264 标准编码的视频数据,不掺杂音频等其他类型信息 。其作用是提供最原始的音视频内容素材,是整个 TS 文件数据的基石,后续各层都是基于此进行加工和处理。
  • PES 层(Packet Elemental Stream,分组基本码流层):在 ES 层基础上构建,主要工作是在 ES 数据中加入时间戳(PTS/DTS)等关键信息。由于 ES 数据包通常较大,为便于传输与处理,会将 ES 流分割成长度不等的数据包,并为每个数据包添加 PES 包头。其中,PTS(Presentation Time Stamp,显示时间戳)用于指示视频帧或音频样本应在何时显示或播放;DTS(Decoding Time Stamp,解码时间戳)指明数据应在何时进行解码。对于视频数据,I 帧和 P 帧一般同时具备 PTS 和 DTS,而 B 帧只需 PTS(因为其解码顺序与显示顺序不同,I、P 帧的 PTS 等于 DTS,若视频无 B 帧,PTS 与 DTS 始终相同) 。PES 层通过这些时间戳信息,确保音视频数据在解码和播放过程中的时间顺序准确无误,实现音视频的同步播放。例如,在一段包含多个 I、P、B 帧的视频 PES 流中,每个帧对应的 PES 包会携带准确的 PTS 和 DTS,播放器依据这些时间戳来决定何时解码、何时显示每一帧画面。
  • TS 层(Transport Stream,传输流层):位于最上层,在 PES 层之上进一步添加了数据流识别信息与传输信息。TS 包大小固定为 188 字节(扩展后为 204 字节,含 16 字节 CRC 校验),由三部分组成:
    • TS Header(TS 包头):固定为 4 字节,是每个 TS 包的起始标识,包含诸多关键控制信息。如同步字节(固定值 0x47,用于快速识别 TS 包起始位置)、传输错误指示(1 位,用于标记该包在传输过程中是否出现错误)、负载单元起始指示(1 位,指示包净荷是否为新的存取单元起始,如视频帧起始)、PID(Packet Identifier,包标识符,13 位,是区分不同数据流的关键,0x0000 代表 PAT 表,0x0001 代表条件访问表等)、连续计数器(4 位,每发送一个相同 PID 的 TS 包,计数器递增 1,从 0 到 15 循环,用于检测包丢失)等。
  • Adaptation Field(自适应字段):并非每个 TS 包都有,其存在的主要目的是为不足 188 字节的数据进行填充,以及插入节目时钟参考(PCR,Program Clock Reference)等重要信息。PCR 对于恢复与编码端一致的时钟顺序至关重要,通常每隔 100ms 至少传输一次,它作为解码器解码时的时钟参考基准,调整本地时钟以与编码端同步。一般在视频帧的首个和最后一个 TS 包中添加自适应字段,中间的 TS 包若无需求则可不加。
  • Payload(有效载荷):承载的数据类型多样,可能是 PES 数据(即音视频数据经 PES 层封装后的结果),也可能是节目专用信息 PSI(如 PAT、PMT 表)。PAT(Program Association Table,节目关联表)用于列出所有节目及对应的 PMT 表 PID;PMT(Program Map Table,节目映射表)针对每个节目,详细定义其包含的音视频流的 PID、编码格式、分辨率等关键参数,是解析 TS 流、分离出音视频流的重要依据。

4.2 重点内容解析

TS 流解析的核心逻辑与 PID 体系
TS 流通过 PID(Packet Identifier) 实现不同类型数据的区分与复用,核心数据类型包括:

  • PAT 表(Program Association Table,PID=0x0000):全局索引表,指向各节目的 PMT 表位置。
  • PMT 表(Program Map Table):节目映射表,定义特定节目包含的音视频流 PID 及编码参数。
  • 音频流 / 视频流:承载实际音视频数据的媒体流。

解析流程:
定位 PAT 表:通过固定 PID(0x0000)获取 PAT 表。
解析 PMT 位置:从 PAT 中提取目标节目的 PMT 表 PID。
获取音视频流:通过 PMT 表找到对应音频流和视频流的 PID。
数据解复用:根据音视频 PID 过滤 TS 包,提取媒体数据

在 TS(Transport Stream)协议和相关流媒体场景中,“节目(Program)” 是一个逻辑概念,用于对音视频内容及相关数据进行分组管理。它可以理解为一个完整的多媒体内容集合,包含了一组相互关联的音视频流、字幕流等,共同构成可供观众观看或收听的完整内容单元
PID 是什么?
就像快递分拣站的 “包裹标签”。

作用:TS 流里有很多种数据(比如视频、音频、节目表等),每个数据都要贴一个 “标签”(PID),这样接收端才能知道 “这个包裹里装的是什么”。
比如:
贴了 “标签 0” 的包裹:里面装的是 “节目总目录”(PAT 表),告诉用户有哪些频道 / 节目。
贴了 “标签 100” 的包裹:里面装的是 “某个频道的视频数据”。
贴了 “标签 200” 的包裹:里面装的是 “这个频道的音频数据”。
特点:
全局唯一:整个 TS 流里,每个标签(PID)只能对应一种数据,不能重复。
必须有:就像快递必须有标签才能分拣,TS 流里的节目表(PAT/PMT)必须用固定标签(如 PID=0)传输,否则接收端看不懂。

自适应区(Adaptation Field)的长度与结构

  • 长度要求:
    自适应区的总长度需包含 传输错误指示符(1 字节)。若实际数据不足,剩余字节用 0xFF 填充(类似补白)。
  • 作用场景:
    视频 / 音频流:必须添加自适应区,通常位于帧的首个 TS 包和最后一个 TS 包,用于插入 PCR 时钟或填充数据。
    PAT/PMT 表:无需自适应区,直接用 0xFF 补足长度即可。
    PCR、DTS、PTS 的关系与作用
    -PCR(节目时钟参考)
    本质
    对系统时钟的采样值,用于解码器同步本地时钟(类似 “时间基准”)。
    特点:
    单调递增(不能回退),通常每 100ms 插入一次。
    仅视频流需要,音频流通过 PTS 与视频同步,无需 PCR。
    -用途:可直接作为 DTS(解码时间戳) 使用,简化时间戳管理。
http://www.xdnf.cn/news/8500.html

相关文章:

  • siparmyknife:SIP协议渗透测试的瑞士军刀!全参数详细教程!Kali Linux教程!
  • Python 训练营打卡 Day 33
  • AI浪潮下,媒体内容运营的五重变奏
  • 安卓新建项目时,Gradle下载慢下载如何用国内的镜像
  • 什么是Express
  • MCP Server 实践之旅第 3 站:MCP 协议亲和性的技术内幕
  • Vue组件化与生命周期:打造灵活高效的前端积木世界
  • 低代码平台搭建
  • VueRouter路由组件的用法介绍
  • Seismic source model -- Brune model ( ω^2 model)
  • 有两个Python脚本都在虚拟环境下运行,怎么打包成一个系统服务,按照顺序启动?
  • 班迪录屏--解决视频剪辑时声音和画面不同步的问题
  • 【COMSOL超材料和超表面仿真设计】
  • Gemma 3n:更智能、更快速、随时离线的AI新纪元
  • leetcode3434. 子数组操作后的最大频率-medium
  • Google Play 账号创建及材料准备
  • 详解MySQL锁机制
  • Python实现栈和队列及其应用场景解析
  • 继续对《道德经》第57章至第81章进行数学形式化建模
  • 高压电工工作内容详解
  • 【PhysUnits】8 关联常量泛型(constant/mod.rs)
  • Oracle 11g导出数据库结构和数据
  • 基于Java的仓库库存管理系统的设计与实现|参考|1w字+
  • 每日一练,冲进国赛!全国青少年信息素养大赛-图形化编程—省赛真题——小鸡吃东西
  • Java注解运行时访问与处理技术详解
  • 修改nmeaLib库增加北斗(BD)和格洛纳斯(GNSS)解析
  • PostGIS实现栅格数据导出TIFF应用实践【ST_AsTiff】
  • 图纸加密软件的核心优势解析
  • Python多线程编程详解
  • 信号与系统02-信号的时域分析