直播原理
视频协议
- HLS协议 [主要是直播方面(好用,但延时)]
HTTP Live Streaming(缩写是HLS)是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。 是苹果公司QuickTime X和iPhone软件系统的一部分。 它的工作原理是把整个流分成一个个小的基于HTTP的文件来下载,每次只下载一些。 当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。 在开始一个流媒体会话时,客户端会下载一个包含元数据的extended M3U (m3u8)playlist文件,用于寻找可用的媒体流。 HLS只请求基本的HTTP报文,与实时传输协议(RTP)不同,HLS可以穿过任何允许HTTP数据通过的防火墙或者代理服务器。 它也很容易使用内容分发网络来传输媒体流。 苹果公司把HLS协议作为一个互联网草案(逐步提交),在第一阶段中已作为一个非正式的标准提交到IETF。 但是,即使苹果偶尔地提交一些小的更新,IETF却没有关于制定此标准的有关进一步的动作。
1. 视频的封装格式是.ts
2. 视频的编码格式为H264,音频编码格式为MP3,AAC或者AC-3
3. 除去TS视频文件本身,还定义了用来控制播放的文件m3u8文件 解析出片段式文件(直播流的片段)
为什么苹果要提出HLS这个协议,其实他的主要是为了解决RTMP协议存在的一些问题。 比如RTMP协议不使用标准的HTTP接口传输数据,所以在一些特殊的网络环境下可能被防火墙屏蔽掉。 但是HLS由于使用的HTTP协议传输数据,不会遇到被防火墙屏蔽的情况(不会有防火墙连80接口都不放过吧) 另外于负载,RTMP是一种有状态协议,很难对视频服务器进行平滑扩展,因为需要为每一个播放视频流的客户端维护状态。 而HLS基于无状态协议(HTTP),客户端只是按照顺序使用下载存储在服务器的普通TS文件, 做负责均衡如同普通的HTTP文件服务器的负载均衡一样简单。 另外HLS协议本身实现了码率自适应,不同带宽的设备可以自动切换到最适合自己码率的视频播放。 其实HLS最大的优势就是他的亲爹是苹果。苹果在自家的iOS设备上只提供对HLS的原生支持,并且放弃了flash Android也迫于平果的“淫威”原生支持了HLS。这样一来flv,RTMP这些Adobe的视频方案要想在移动设备上播放需要额外下点功夫。 当然flash对移动设备造成很大的性能压力确实也是自身的问题。
* 但HLS也有一些无法跨越的坑,比如采用HLS协议直播的视频延迟时间无法下到10秒以下,而RTMP协议的延迟最低可以到3、4秒左右。所以说对直播延迟比较敏感的服务请慎用HLS。
- RTMP协议
- RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。该协议基于TCP,是一个协议族,包括RTMP基本协议以及RTMPT/RTMPS/RTMPE等多种变种、RTMP是一种设计用来进行实时数据通信的网络协议,主要用来在Flash、AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信(实时性比较好,但使用比较复杂)
- HTTP-FLV协议(直播协议)
- 不需要处理应答机制,因为基于HTTP协议,建立长链接。(结合两者的优点,好用,实时性好,但是flv格式)
- 可以在一定程度上避免防火墙的干扰(比如,有的机房只允许80端口通过)
- 内容很好的兼容HTTP 302跳转,做到灵活调度
- 可以使用HTTPS做加密通道
- 很好的支持移动端(Android,IOS)
1. 了解直播使用的分类
2. 理解对应协议的通信原理
3. 理解直播协议之间的区别 4. 掌握不同场景采用什么协议 (采集(用客户端)用RTMP。低延迟的场景,用RTMP、HTTP-FLV。延时要求不高,可以用HLS)
支持格式
格式\浏览器 | Chrome | Firfox | Safari | 描述 |
---|---|---|---|---|
mp4 | √ | √ | √ | 兼容性好 |
webm | √ | √ | 流式视频格式 | |
hls | √ | 视频协议 视频格式是 .ts 苹果自身研究出来的 Safari能用 | ||
flv |
Video属性和方法
属性 | 属性 |
---|---|
贴图poster | 自动播放autoplay |
控制条controls | 循环播放loop |
预加载preload | 音量volume |
播放地址设置 | 静音muted |
播放时间设置 |
事件 | 事件 |
---|---|
视频查找 | 时长变化 |
元数据加载 | 视频下载监听 |
可播放监听 | 播放监听 |
暂停监听 | 查找开始 |
查找结束 | 视频加载等待 |
视频结束 |
Video的标签,属性和方法
<!-- 显示控制条 -->
<video src="./test.mp4" id="vs" width="400" height="225" controls ></video>
<!-- 禁用控制条的某个按钮 例如下载,全屏等 -->
<video src="./test.mp4" controls controlslist="nodownload nofullscreen"></video>
<!-- 贴图 -->
<video src="./test.mp4" width="400" height="225" controls poster="./poster.jpg"></video>
<!-- 自动播放 -->
<video src="./test.mp4" width="400" height="225" autoplay controls "></video>
<!-- 静音 -->
<video src="./test.mp4" width="400" height="225" muted controls ></video>
<!-- 循环播放 -->
<video src="./test.mp4" width="400" height="225" muted loop controls ></video>
<!-- 预加载 -->
<video src="./test.mp4" width="400" height="225" preload controls ></video>
<!-- 音量控制 -->
<video src="./test.mp4" id="_volume" width="400" height="225" controls></video>
<script type="text/javascript">
var v = document.getElementById('_volume');
v.volume = 0.5;
</script>
<!-- 播放时间控制 设置从当前多少秒开始播放,可用于跳过片头-->
<video src="./test.mp4" id="_time" width="400" height="225" controls></video>
<script type="text/javascript">
var v = document.getElementById('_time');
console.log(v.currentTime);
v.currentTime = 60;// 单位:秒
</script>
<!-- 播放地址的切换 -->
<video src="./test.mp4" id="_src" width="400" height="225" controls></video>
<script type="text/javascript">
var v = document.getElementById('_src');
console.log(v.src);
setTimeout(function() {
v.src = './test-2.mp4';
}, 2000);
</script>
<!-- 备用地址切换 -->
<video id="_source" controls width="400" height="225">
<source src="./test3.mp4" type="video/mp4">
<source src="./test4.mp4" type="video/mp4">
</video>
<script type="text/javascript">
var v = document.getElementById('_source');
setTimeout(function() {
console.log('src', v.currentSrc)
}, 1000);
</script>
--------------------------------- 华丽的分割线 ------------------------------------------
<!-- 所有关于Video播放的监听事件 (看情况,使用对应的监听事件)-->
<!-- 顶格注释内容,为常用监听事件,其他视项目实际情况而定! -->
<script type="text/javascript">
// 视频监听
var v = document.getElementById('vs');
console.log('v.duration', v.duration);
// loadstart
v.addEventListener('loadstart', function(e) {
console.log('loadstart', v.duration);
});
// durationchange 时长变化(拿到总时长)
v.addEventListener('durationchange', function(e) {
console.log('durationchange', v.duration);
});
// loadedmetadata (拿到元数据)
v.addEventListener('loadedmetadata', function(e) {
console.log('loadedmetadata');
});
// loadeddata(不够帧去播放)
v.addEventListener('loadeddata', function(e) {
console.log('loadeddata');
});
// progress(下载时候触发)
v.addEventListener('progress', function(e) {
console.log('progress');
});
// canplay(准备完成,下载好了)
v.addEventListener('canplay', function(e) {
console.log('canplay');
});
// canplaythrough(足够帧数播放了)
v.addEventListener('canplaythrough', function(e) {
console.log('canplaythrough');
});
// play(播放)
v.addEventListener('play', function(e) {
console.log('play');
});
// pause (暂停)
v.addEventListener('pause', function(e) {
console.log('pause');
});
// seeking(点某个位置)
v.addEventListener('seeking', function(e) {
console.log('seeking');
});
// seeded (下载那个点的视频可播放了,触发,即seeking结束)
v.addEventListener('seeked', function(e) {
console.log('seeded');
});
// waiting(当没有足够数据播放时,触法play时间时,会触发waiting事件)
v.addEventListener('waiting', function(e) {
console.log('waiting');
});
// playing
v.addEventListener('playing', function(e) {
console.log('playing');
});
// timeupdate(精确获取播放时间更新的事件)
v.addEventListener('timeupdate', function(e) {
console.log('timeupdate');
});
// ended(结束事件)
v.addEventListener('ended', function(e) {
console.log('ended');
});
// error(报错信息)
v.addEventListener('error', function(e) {
console.log('error', e);
});
</script>
常用的视频js库
video.js的其他插件 其中 关于video.js的hls插件
flv.js地址的github上找源js文件比较难找,可以通过打开demo,查看源代码拷贝下来
博客大神的调研https://blog.csdn.net/ahoustep/article/details/52175732
一、市场上哪家直播使用了http-flv:
通过抓包分析: 优酷的pc网页直播使用了http-flv。
斗鱼、熊猫tv、虎牙pc网页上的也使用了http-flv。
二、http-flv、rtmp和hls直播的优缺点:
A、三者的延迟性:
http-flv:低延迟,内容延迟可以做到2-5秒。 Rtmp:低延迟,内容延迟可以做到2-5秒。 Hls::延迟较高。 B、三者的易用性: rtmp和http-flv:播放端安装率高。只要浏览器支持FlashPlayer就能非常简易的播放。 hls:最大的优点:HTML5可以直接打开播放;这个意味着可以把一个直播链接通过微信 等转发分享,不需要安装任何独立的APP,有浏览器即可。 C、rtmp和http-flv比较: (1) 穿墙:很多防火墙会墙掉RTMP,但是不会墙HTTP,因此HTTP FLV出现奇怪问题的概率很小。 (2) 调度:RTMP也有个302,可惜是播放器as中支持的,HTTP FLV流就支持302方便CDN纠正DNS的错误。 (3) 容错:SRS的HTTP FLV回源时可以回多个,和RTMP一样,可以支持多级热备。 (4) 简单:FLV是最简单的流媒体封装,HTTP是最广泛的协议,这两个组合在一起维护性更高,比RTMP简单多了。
三、http-flv技术实现:
HTTP协议中有个约定:content-length字段,http的body部分的长度 服务器回复http请求的时候如果有这个字段,客户端就接收这个长度的数据然后就认为数据传输完成了, 如果服务器回复http请求中没有这个字段,客户端就一直接收数据,直到服务器跟客户端的socket连接断开。 http-flv直播就是利用第二个原理,服务器回复客户端请求的时候不加content-length字段,在回复了http 内容之后,紧接着发送flv数据,客户端就一直接收数据了。
四、使用和测试http-flv:
使用开源的SRS服务器,SRS2.0版本是开源,后续的版本已经闭源。
推流端以rtmp的形式推流到srs服务器,srs再把rtmp流转换成http-flv流。 请求SRS返回的是: HTTP/1.1 200 OK Connection: Keep-Alive Content-Type: video/x-flv Server: SRS/2.0.205 Transfer-Encoding: chunked 请求某个电视台http://fms.cntv.lxdns.com/live/flv/channel2.flv,返回的是: HTTP/1.1 200 OK Cache-Control: no-cache Content-Type: video/x-flv Expires: -1 Pragma: no-cache