流媒体协议简析-HLS、HTTP-FLV与RTMP

推流与拉流

  • 推流:视频生产端生产视频,并将视频流式上传至服务器的过程(直播中的主播端)

  • 拉流:客户端根据url从服务器或者边缘节点缓存中流式拉取视频的过程(直播中的观众端)

HLS

基本原理

HLS(HTTP Live Streaming) 是由Apple提出的基于HTTP协议的流媒体传输协议。

HLS的基本原理就是将一个比较大的视频切成视频片段(ts格式的),然后将切片记录在索引文件(m3u8文件)内。我们在播放的时候,先获取到索引文件,然后根据索引文件将视频切片请求回来拼到一起就可以播放了。基本结构如下

m3u8索引

一个HLS播放源其实就是一个m3u8的文件地址,例如devimages.apple.com/iphone/samp...

PlainText 复制代码
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10, no desc
fileSequence0.ts
#EXTINF:10, no desc
fileSequence1.ts
#EXTINF:10, no desc
fileSequence2.ts
...

m3u8文件每一行,要么是#开头的字符串,要么就是一个资源URI。 其中#EXT开头的为标签,例如#EXTINF:10, no desc 就代表了一个媒体文件标签,同时标明这个文件长10秒,下边对应的资源URI这个媒体文件的URI。其他常用的标签还有

  • #EXT-X-MEDIA-SEQUENCE,标记了起始媒体的序列号

  • #EXT-X-TARGETDURATION,每个视频段的最大时长

  • #EXT-X-ENDLIST,代表媒体文件的结尾。不添加#EXT-X-ENDLIST暗示索引会动态更新,适用于直播场景

播放器拿到文件地址后,会根据播放时间去请求对应的ts片段回来。作为Apple的亲儿子,safari对hls有原生支持,我们可以直接用safari浏览器访问这个m3u8 url,可以看到控制台对ts视频片段的请求

ts文件也可以用mac自带的QuickTime Player打开,是一个10秒的视频片段,和标签描述的一样

多级索引

m3u8也支持定义不同的播放索引,可供播放器根据网络环境、播放器尺寸等因素自行选择合适的媒体索引进行播放,例如devstreaming-cdn.apple.com/videos/wwdc...

SQL 复制代码
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",BANDWIDTH=2513649,AVERAGE-BANDWIDTH=571502,FRAME-RATE=29.970,AUDIO="program_audio_0",SUBTITLES="subs"
cmaf/avc/720p_4500/avc_720p_4500.m3u8
#EXT-X-STREAM-INF:RESOLUTION=960x540,CODECS="avc1.4d401f,mp4a.40.2",BANDWIDTH=1282475,AVERAGE-BANDWIDTH=389378,FRAME-RATE=29.970,AUDIO="program_audio_0",SUBTITLES="subs"
cmaf/avc/540p_2000/avc_540p_2000.m3u8
#EXT-X-STREAM-INF:RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2",BANDWIDTH=2513650,AVERAGE-BANDWIDTH=571503,FRAME-RATE=29.970,AUDIO="program_audio_0",SUBTITLES="subs"
.....

hls.js

除了safari外,大部分主流浏览器原生不支持HLS协议。所以需要一定的转换,通常会使用hls.js。hls.js使用的是MSE+HTML5 video的方案

MSE,全称Media Source Extensions API,开发者能够动态构造 MediaSource 对象,然后通过 URL.createObjectURL() 创建一个形如blob:<origin>/<uuid>的URL(我们可以经常在视频网站上看到这种形式的URL),将这个URL传给html video组件,就可以实现视频片段的合并播放了。

由于video标签并不支持ts封装格式,所以需要将ts封装的视频片段先解封装出h264编码的数据,然后再封装成Fragment MP4 格式的片段(fMp4)再传给播放器。

优势与劣势

优势

  • 适配性好,基于无状态的HTTP协议,对服务端要求低,CDN不需要特别的改造即可部署HLS。并且HTTP协议通用,不容易被防火墙拦截

  • 支持码率自适应,可以根据不同的设备环境选择不同的视频流

  • 天生对Apple设备有良好的支持

劣势

  • 由于需要在服务端对资源进行切片处理,整体延迟会比较高。因此HLS多用于点播场景,对于直播场景则多用于拉流,不太适合推流。

  • 客户端频繁地进行http请求有相应的代价,容易被其他请求影响导致播放卡顿

DASH

DASH和HLS原理很像,都是用索引(DASH使用.mpd文件,xml格式)搭配HTTP请求视频片段的方式实现流媒体播放。不同的是HLS是Apple公司的标准,而DASH是国际标准,支持更多的封装格式与编码。

HTTP-FLV

基本原理

HTTP-FLV的传输方式是基于Stream API,需要与服务器建立长连接,传输一个无限大小的FLV文件。

FLV也是一种比较常见的封装格式了,最早是flash动画的视频格式。对于比较常见MP4格式,MP4格式有复杂的box结构,并且存储元信息的moov box会随着视频的内容变化而变化,不适合动态处理。而FLV的格式比较轻巧简单,格式如下

可以看到FLV Header不会随着视频的内容改变而变化,FLV Body则是分成一个Tag来组织,每个Tag都可以单独被解析,天生适合流式传输,因此现在被广泛用在流媒体传输。不过大部分浏览器都不支持直接播放flv视频,目前基本也是基于MSE进行重封装后播放(使用flv.js)

优势与劣势

优势

  • 基于HTTP协议,不容易被防火墙拦截

  • 无需切片处理,随播随推延迟低,所以多用于低延迟直播场景

劣势

  • 需要与服务器建立长连接,需要专用的推流CDN,有改造成本。并且不能实时的切换不同视频流,不利于网络环境适配

  • FLV封装的媒体类型支持不算广泛,需要客户端支持播放FLV。对于浏览器端,依赖MSE与Stream API,尤其是ios系统不支持MSE,导致无法在ios端浏览器使用

RTMP

基本原理

RTMP,全称 Real Time Messaging Protocol,即实时消息传送协议,最早是为 Flash 播放器和服务器之间音视频数据传输开发的私有协议,为Adobe公司所有。该协议是一个应用层协议,基于TCP协议,默认使用1935端口。RTMP的用户端首先会和服务器进行握手,如下图

双方互相交换三个数据包(chunk)后,建立起一个稳定的链接进行通信。RTMP中的数据单位为message,在实际传输中会将Message切成一个个更小的chunk来传输,由message stream id来标识chunk是否来自同一个message。媒体端接收到message后再将数据拼接成音视频进行播放。

优势与劣势

优势

  • RTMP基于数据包传输,不需要切片处理,延迟很低

  • RTMP作为专供流媒体传输的协议,对底层支持优秀,有很多硬件视频编码设备与CDN支持RTMP协议

劣势

  • 非通用端口容易被防火墙拦截

  • 适配性不好,尤其是对于web端,在flash被禁用后几乎无法使用。因此通常用于推流,或者服务器之间的推拉流。播放器端的拉流通常需要由其他协议完成。

相关推荐
dvlinker2 天前
【音视频开发】使用支持硬件加速的D3D11绘图遇到的绘图失败与绘图崩溃问题的记录与总结
音视频开发·c/c++·视频播放·d3d11·d3d11绘图模式
音视频牛哥7 天前
Android平台GB28181实时回传流程和技术实现
音视频开发·视频编码·直播
音视频牛哥8 天前
RTMP、RTSP直播播放器的低延迟设计探讨
音视频开发·视频编码·直播
音视频牛哥12 天前
电脑共享同屏的几种方法分享
音视频开发·视频编码·直播
x007xyz2 个月前
前端纯手工绘制音频波形图
前端·音视频开发·canvas
音视频牛哥2 个月前
Android摄像头采集选Camera1还是Camera2?
音视频开发·视频编码·直播
九酒2 个月前
【harmonyOS NEXT 下的前端开发者】WAV音频编码实现
前端·harmonyos·音视频开发
音视频牛哥2 个月前
结合GB/T28181规范探讨Android平台设备接入模块心跳实现
音视频开发·视频编码·直播
哔哩哔哩技术2 个月前
自研点直播转码核心
音视频开发