流媒体网络协议 -- HLS
HLS
- HLS介绍
- 1. 原理
- 2. HLS多媒体系统
- 3. HLS的优势和不足:
- 媒体描述文件
- 1. 主播放列表(Master Playlist)
- 2. 媒体播放列表(Media Playlist)
- 3. 播放列表中URL生成规则:
- 4. 扩展
- 实际应用遇到的问题
HLS介绍
HLS(HTTP Live Streaming)全称为http直播流,是一个由Apple公司提出的基于HTTP的媒体流传输协议,用来实现实时音视频流的传输。
1. 原理
服务器将码流切割成一个个小的(通常是10秒一个)可以通过HTTP下载的媒体分片(segment),并提供一个配套的媒体列表文件(M3U8文件);客户端下载媒体列表文件,并按照规范解析文件,获取每个媒体分片的地址并按顺序下载,从而实现看起来播放一个码流的效果。
这其中,HTTP是网络协议,媒体播放列表为Apple官方定义的M3U8文件,媒体文件格式为TS或fMP4。
2. HLS多媒体系统
该系统结构如下图:
主要由四个部分组成:
- 媒体资料输入源
采集音视频数据 - 媒体编码封装服务器
对裸流进行编码,封装,切割,使之成为连续的、时长很短的媒体文件。 - 分发服务器
标准的网络服务器组成,接收客户端的请求和分发资源(M3U8文件和媒体文件) - 客户端
拉流播放
3. HLS的优势和不足:
- 优势:
- 使用HTTP协议传输数据,不会被防火墙屏蔽掉,易于分发。
- 码率自适应,提高播放流畅度。
- 无状态协议,便于负载均衡。
- 浏览器支持好,无需安装插件。
- 不足:
实时性差,延迟高,两个原因:
1>采用切片式的多媒体文件,因为切片需要时间编码,所以一个切片的延时不可避免。
2>使用http短连接,需要不断的与server建立连接,且基于tcp,需要三次握手,四次挥手,交互耗时长。
媒体描述文件
M3U8文件,HLS的媒体描述文件,UTF-8编码。
可以是一个主列表(Master Playlist),也可以是一个媒体列表(Media Playlist)。
如下图为列表和媒体文件的关系,共两级列表。
1. 主播放列表(Master Playlist)
用来表示多个不同码率码流的媒体播放列表url及相关信息。
如下:
#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS="avc1.640028,mp4a.40.2"
http: //example.com/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS="avc1.640028,mp4a.40.2"
http: //example.com/mid.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS="avc1.640028,mp4a.40.2"
http: //example.com/hi.m3u8
TAG以及形式 | 意义 |
---|---|
#EXTM3U | 表示该文件一个拓展的M3U8文件,必须放在第一行。 |
#EXT-X-STREAM-INF: |
用于指定一个Variants Stream,指定一个包含多媒体信息的Media URI作为playlist 一般做M3U8的嵌套使用,它只对紧跟后面的URI有效。 attribute-list有以下参数: · BANDWIDTH: 要求的带宽,该参数必须有,实现码率自适应的关键参数。 · PROGRAM-ID: 十进制整数,唯一地标识playlist文件范围内的特定描述。 · CODECS: 指定视频和音频编码类型,非必须的。 · RESOLUTION: 分辨率,非必须的。 |
2. 媒体播放列表(Media Playlist)
用来表示同一码率码流的一系列切片url及相关信息。
- 点播的媒体播放列表:
#EXTM3U #EXT-X-PLAYLIST-TYPE:VOD // 播放列表类型 #EXT-X-VERSION:3 // 版本信息 #EXT-X-TARGETDURATION:11 // 每个分片的目标时长 #EXT-X-MEDIA-SEQUENCE:0 // 该文件第一个分片的序号 #EXTINF:10.922578, // 分片实际时长 test000.ts // 第一个分片文件,序号为0 #EXTINF:9.929578, // 第二个分片实际时长 test001.ts // 第二个分片文件,序号为1 ... #EXT-X-ENDLIST // 该列表结束标志
- 对于加密的码流,多了EXT-X-KEY tag,用以表示加密方法、key的请求地址和IV(偏移量)
注意需要将IV转化为十六进制(char --> hex)
其媒体播放列表是这样的:#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:12616381 #EXT-X-KEY:METHOD=AES-128,URI="3M_key",IV=0x4F1E7B58678D094361DF3F0FFDEDD333 #EXTINF:10, 720p_aes_0.ts #EXT-X-KEY:METHOD=AES-128,URI="3M_key",IV=0x4F1E7B58678D094361DF3F0FFDEDD333 #EXTINF:10, 720p_aes_1.ts #EXT-X-ENDLIST
- 对于直播流,其媒体播放列表末尾没有ENDLIST tag,是这样的:
EXT-X-PLAYLIST-TYPE为EVENT,而且列表末尾没有EXT-X-ENDLIST tag! #EXTM3U #EXT-X-PLAYLIST-TYPE:EVENT #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:11 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.922578, test000.ts #EXTINF:9.929578, test001.ts ...
- 下面说明各个TAG的意义:
TAG以及形式 意义 #EXTM3U 一个拓展的M3U8文件,必须放在第一行,以此TAG来说明该文件为M3U8文件 #EXT-X-PLAYLIST-TYPE 播放列表类型。有两个取值:VOD --> 点播;EVENT --> 直播。 #EXT-X-VERSION: 协议的版本号,n为3,HLS v3;n为4,HLS v4 #EXT-X-TARGETDURATION: 该列表中每个切片的最大时长 #EXT-X-MEDIA-SEQUENCE: 该文件第一个切片的序号。如没有,则默认为0 #EXTINF:duration(float),title 一个切片的实际时长和文件名,文件名与url拼接就可以得到切片url。 #EXT-X-KEY 解密信息,有三个参数:
• METHOD:加密算法,hls协议规定三个枚举值:NONE, AES-128(CBC), SAMPLE-AES
• URI:解密key相对资源路径
• IV:解密偏移量#EXT-X-ENDLIST M3U8文件结束符,直播场景没有这个tag
3. 播放列表中URL生成规则:
播放列表中有以下几种不同的URL生成规则。
直接给出URL
也就是绝对路径,拿到之后直接用来请求既可。如:#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
那我们直接请求http://media.example.com/first.ts,就可以拿到切片了
单文件名相对路径
只给出文件名,说明资源文件与m3u8文件放在一个目录,需要进行url拼接。如:#EXTM3U #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
拼接规则:将请求该m3u8文件的url去掉m3u8文件名后,再将切片文件名拼接上去,就是正确url了。
如该m3u8的url为:http://media.example.com/index.m3u8 那么每个切片url前缀就是:http://media.example.com/ 所以第一个切片url就是:http://media.example.com/first.ts
带文件路径的相对路径
给出资源文件的路径,说明资源文件与m3u8文件不放在同一个目录,需要进行url拼接,如:#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608 1000k/hls/index.m3u8 或者: #EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608 /1000k/hls/index.m3u8
拼接规则同2)。
如该m3u8的url为:http://media.example.com/index.m3u8 那么每个媒体播放列表url前缀就是:http://media.example.com/ 所以该媒体播放列表的url就是:http://media.example.com/1000k/hls/index.m3u8
还有一种:
#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608 /15467_73a719b2/1000k/hls/index.m3u8
而请求该m3u8的url是:
http://media.example.com/123/15467_73a719b2/index.m3u8
可以看到文件路径和请求url有重复的地方,这种情况需要去重。
按2)的拼接规则,那么就是:http://media.example.com/123/15467_73a719b2/15467_73a719b2/1000k/hls/index.m3u8
显然不对,需要去重,所以应该是:
http://media.example.com/123/15467_73a719b2/1000k/hls/index.m3u8
双斜杆相对位置:
双斜杆后面一般直接就是域名,如:#EXTM3U #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=800000,RESOLUTION=1080x608 //douban.donghongzuida.com/20210109/15467_73a719b2/1000k/hls/index.m3u8
拼接规则:直接添加请求该m3u8列表的协议。
如该m3u8为http://media.example.com/index.m3u8, 那么就是:http://douban.donghongzuida.com/20210109/15467_73a719b2/1000k/hls/index.m3u8 如该m3u8为https://media.example.com/index.m3u8, 那么就是:https://douban.donghongzuida.com/20210109/15467_73a719b2/1000k/hls/index.m3u8
4. 扩展
HLS高版本中支持了ISO profile,也就是支持fragment MP4,为此HLS新增了EXT-X-MAP这个tag来标识。
如:#EXTM3U #EXT-X-TARGETDURATION:15 #EXT-X-ALLOW-CACHE:YES #EXT-X-PLAYLIST-TYPE:VOD #EXT-X-VERSION:6 #EXT-X-MEDIA-SEQUENCE:1 #EXT-X-MAP:URI="init-v1-a1.mp4" #EXTINF:13.000, seg-1-v1-a1.m4s #EXTINF:12.000, seg-2-v1-a1.m4s #EXT-X-ENDLIST
fragment mp4的moov和mdat是分开的,在hls中,承载moov的切片叫做init segment;而承载mdat的切片叫做media segment。
而为了区分两者,就有了EXT-X-MAP这个tag,用以表示init segment的url。meidia segment中可能有audio和video fragement。
而对于TS profile,也可以使用EXT-X-MAP,其init segment就是PAT和PMT的packet,这可以提高ts的负载率。低延时HLS的实现
1>第三方公司提出的LHLS方案
HTTP 1.1 分块传输(chunk)
参考链接:https://www.theoplayer.com/low-latency-hls-streaming2> apple官方提出的low-latency HLS方案
最大的改进是将最新的那个切片分解成更小的切片,也就是请求的数据颗粒度更小了,可访问切片的生成时间减小,时延减小。
为此,特别新增了#EXT-X-PART这个tag.
如:#EXTINF:6.003, LLHLS_Video1_67750710.mp4 #EXT-X-PROGRAM-DATE-TIME:2021-03-18T09:20:29.482Z #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.0.mp4",INDEPENDENT=YES #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.1.mp4",INDEPENDENT=YES #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.2.mp4",INDEPENDENT=YES #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.3.mp4",INDEPENDENT=YES #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.4.mp4",INDEPENDENT=YES #EXT-X-PART:DURATION=1.000,URI="LLHLS_Video1_67750711.5.mp4",INDEPENDENT=YES
可见LLHLS_Video1_67750710.mp4这个切片被切分成更小的切片,这样就不用等待该切片整个生成之后,再去访问了。
搭建HLS服务器。
使用nginx或Apache2搭建Http server即可…如何在hls播放过程中插播广告?
同一个广告视频应当可以插入到任意hls片源的任意切片前面,因此无法保证广告视频的编码格式和码率等信息和HLS片源是一致的,这会影响客户端播放器的正常播放,因此有必要告知播放器广告插入在hls片源插入的时间点以及广告的metadata等信息。HLS专门设置了#EXT-X-DISCONTIUITY这个TAG来表明前面切片和后面切片是完全不同的,需要播放器做出对应的处理。播放器检测的这个tag之后就需要重新初始化解码器,因为切片的编码类型发送变化。
例子:
一个普通的M3u8文件:#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:11 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.922578, test000.ts #EXTINF:9.929578, test001.ts ...
如果想在原视频开头前插入广告:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:11 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, ad0.ts #EXTINF:8.0, ad1.ts #EXT-X-DISCONTINUITY #EXTINF:10.922578, test000.ts #EXTINF:9.929578, test001.ts ...
如果想在原视频中间插入广告:
#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:11 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.922578, test000.ts #EXT-X-DISCONTINUITY #EXTINF:10.0, ad0.ts #EXTINF:8.0, ad1.ts #EXT-X-DISCONTINUITY #EXTINF:9.929578, test001.ts ...
码率切换策略:
综合考虑网络带宽和buffer水位。
当前带宽小于当前播放码率且buffer中的数据也不充足(不足够一个切片)的时候,降到对应的码率。
当前带宽大于当前播放码率且buffer中的数据充足(大于一个切片)时,升到对应的码率。
怎么计算当前buffer中的切片数量?
通过buffer中数据量和上一个已下载的切片平均比特率来计算当前buffer中是否足够一个切片的时长(targetduration)
实际应用遇到的问题
直播时,playlist请求的间隔是多少?
答:一般是间隔一个切片的时长更新一次播放列表,以减少服务器负担。直播时,第一个播放片段的选择?
答:HLS协议规定直播时,客户端应该选择距离播放列表中最后一个切片大于两个目标时长的切片作为首个切片进行播放。
First_req_segment_sequence <= last_segment_in_list_sequence – 3。
为了兼顾实时性和流畅度,一般而言,客户端应该从m3u8文件中倒数第三个或倒数第四个segment开始播放。如何判断播放源是直播还是点播?
答:有两种方法进行判断
1>判断媒体播放列表是否存在#EXT-X-ENDLIST标签,有,点播;无,直播。
2> 判断#EXT-X-PLAYLIST-TYPE的类型:#EXT-X-PLAYLIST-TYPE: VOD // 点播源
#EXT-X-PLAYLIST-TYPE: EVENT // 直播源如何判断某个M3U8文件是主播放列表还是媒体播放列表?
答:通过列表中是否存在EXT-X-STREAM-INF,存在,主m3u8列表;不存在,媒体播放列表。直播时,如何判断当前请求的m3u8文件相比上一次请求的m3u8文件,是否有新的segment url加入?
答:一个效率比较高的方法是比较上一次请求的m3u8文件和当前m3u8文件的md5码是否一样。一样,无更新,可跳过解析;不一样,有更新。如果m3u8列表请求不到,downloader会怎么处理?
答:retry两次,每次retry等待时长为10秒,如果还请求不到的话,就返回error给player。为什么HLS的实时性差?
答:两个原因:
1>采用切片式的媒体形式,颗粒度大,切片需要编码完成才可以被请求,一个切片的时延不可避免。
2>采用http短连接进行数据请求,需要不断跟服务器请求响应,每次请求需要耗费一个RTT时间,交互时间长。
流媒体网络协议 -- HLS相关推荐
- 流媒体网络协议 -- DASH
DASH DASH介绍 1. DASH工作原理 2. DASH相比于HLS的优势: 媒体描述文件 MPD文件夹解析 1. SegmentBase形式: 2. SegmentList形式: 3. Seg ...
- 流媒体网络协议 -- RTSP
RTSP RTSP介绍 1. 与HTTP协议的异同 2. RTSP的特性 RTSP原理 1. RTSP会话交互过程 2. RTSP客户端状态机 3. RTSP server保活机制 RTSP请求与回应 ...
- 网络协议从入门到底层原理(11)网络爬虫、无线网络、HTTP缓存、即时通信、流媒体
补充知识 网络爬虫 网络爬虫的简易实例 robots.txt 无线网络 HTTP 缓存(Cache) 缓存 - 响应头 缓存 - 请求头 缓存的使用流程 即时通信(IM) XMPP MQTT 流媒体 ...
- 技术博客|第15期:流媒体传输协议简介 - HLS协议
在Hulu及Disney+流媒体平台上,自适应流媒体传输技术被广泛使用,它可以根据用户的网络情况相应地调整视频码率,为用户带来良好的观看体验.为了实现这一点,视频将被编码成不同码率的版本,并且在每个版 ...
- 网络协议 14 - 流媒体协议
大家都会关注"在浏览器输入一个地址,然后回车,会发生什么"这样一个问题,但是有没有想过这样一个问题:主播开始直播,用户打开客户端观看,这个过程发生了什么? 随着技术的发展, ...
- 流媒体协议HLS解析
参考资料:https://www.cnblogs.com/jimodetiantang/p/9133564.html https://cloud.tencent.com/developer/artic ...
- 直播所使用的网络协议(RTP\RTCP\RTSP\RTMP\HLS\SRT)
目录 直播所用协议的需求 如何选择TCP/UDP? RTP RTP协议是什么? 为什么使用RTP协议? RTCP RTCP协议是什么? 为什么使用RTCP协议? RTSP RTSP协议是什么? 为什么 ...
- 趣谈网络协议 - 第16讲 | 流媒体协议:如何在直播里看到美女帅哥?
可以看到RTMP也是基于TCP的,本质还是通信协议.所以弄音视频流媒体也是离不开这个. 转载自: https://time.geekbang.org/column/intro/100007101 ht ...
- 网络协议学习笔记 · 22
IPv6 · 流媒体 · 即时通讯 · 缓存 · 网络爬虫 VPN 作用 VPN与代理的区别 实现原理(隧道协议) 网络爬虫 简易实例 robots.txt 无线网络 缓存(Cache) 响应头 请求 ...
最新文章
- Windows下Node.js开发入门(1)
- 页面生成周期中的两个Application池的详情小弟了解
- python psutils
- 免费开源分布式系统日志收集框架 Exceptionless
- flink的scala版本的wordcount+flink没有输出结果的几种原因
- js中的事件循环和宏任务和微任务的理解
- 华为的鸿蒙系统是海思_死心了!华为鸿蒙系统首款终端确认,不是手机
- java排序算法原理_排序算法原理与实现(java)
- 【网站推荐】Solaris 平台编写设备驱动程序
- 『真实故事』我经历了坏人变老了
- nmap +shell脚本实现内网端口巡检
- 小米笔记本Air13.3扩充硬盘
- Linux Wps 缺少字体
- 红帽6.2 DOS无盘 NetWare 制作
- 2020十大科技趋势展望
- 12个面向前端开发者真正有用的 VSCode 插件工具
- php出现网页无法运作怎么处理,该网页无法正常运作怎么解决?
- 51nod 1677——treecnt
- linux美化桌面,Linux_设置动态壁纸来美化Ubuntu桌面,我们知道你想拥有一个有格调 - phpStudy...
- Android使用MediaCodec和OpenGL对多段视频画面进行裁剪和拼接