研究了几天的b站的直播,理清了大概的思路,做下总结(文尾附源码)。
本文用的技术:vuejs,flvjs,vue-video-player,videojs-contrib-hls,阿里云视频web播放器。
本文以B站为例来做解析。
开始之前
正式介绍一大堆专业名词之前,先问几个问题。
- 为什么b站要做h5视频播放器。
- 为什么chrome默认禁止了flash。
好吧,带着这两个问题我要开始吹水了。。
为什么b站要做h5视频播放器
在B站推出H5播放器之前,B站PC端的视频使用的可能是RTMP或HTTP-FLV协议(这两个协议功能类似,只是后者没有专利限制),视频格式是flv。RTMP协议是Adobe公司提出的,要使用RTMP或HTTP-FLV协议来传输播放视频,只能使用Flash播放器。
这样想其实没什么问题,那就用flash播放器咯,可是,有个很致命的问题,所有ios设备都不支持flash,也就是说所有iphone、ipad都不支持RTMP或HTTP-FLV协议的视频流,但是支持苹果自家的hls协议,而在ios设备上,h5支持播放hls协议的视频流,所以,B站要留住ios用户,使用h5播放器是大势所趋。
至于为什么苹果不支持flash,归结起来有几个原因:
- 耗电,在mac使用会明显发热。
- h5完全开源,flash是商业化产品。
- flash对触摸支持不够好。
- 安全性问题,内置flash意味着有可能引入相关漏洞,主动权在adobe手上。
- 基于Flash平台的应用非常丰富,很有可能威胁到苹果自家的AppStore。
有兴趣的可以去看看知乎上这个问题:苹果为什么不支持flash,而是用html5技术呢?
为什么chrome默认禁止了flash
这个问题,就一句话,google baba想让flash死,广告费都不想挣了,什么想法可想而知。
这个问题可以看看这个同类问题:chrome默认禁止flash的意图是什么?
回到上一个的问题,既让google都默认禁止了flash了,那b站如果一如既往的只支持flash,那后果也可想而知。
进入正题
有了上面的知识储备,先理清一下关系。
- b站PC端的视频格式是flv,但是b站也可能有淘汰flash的想法,研发了flvjs,实现了flash播放器向h5播放器的平滑过渡,现在mac上也可以直接看B站的视频而不需要下flash。
- 苹果自己推出了视频协议fls,在ios设备上,已得到h5的支持。
- 目前不只ios设备,在大多数android设备上,也原生支持hls协议。也就是说,大部分移动设备上,使用h5的
video
标签都能直接播放hls视频流,而不需要增加其他额外支持。
上面介绍了很多名词,现在做下简单介绍,才能继续讲下面的。
主流直播协议对比
协议 | httpflv | rtmp | hls | dash |
---|---|---|---|---|
传输方式 | http流 | tcp流 | http | http |
视频封装格式 | flv | flv tag | ts文件 | Mp4 3gp webm |
延时 | 低 | 低 | 高 | 高 |
数据分段 | 连续流 | 连续流 | 切片文件 | 切片文件 |
H5播放 | 可通过h5解封包播放(flvjs) | 不支持 | 可通过H5解封包播放(hlsjs) | 如果dash文件列表是mp4webm文件可直接播放 |
其他 | 需要flash支持 | 需要 flash支持 |
详细的介绍请戳:全面进阶 H5 直播
原生h5支持格式
大家都知道h5中的video标签能播放视频,但是视频格式有限制,目前只支持mp4,ogg,webm
这三种格式。
1 | <video controls autoplay> |
那么问题来了,我想用<video>
标签来播放flv格式的视频,播放hls协议视频流,要怎么办。这就是接下来要讲的内容。
H5与PC的直播方案
接下来的介绍仅从前端的角度出发,视频源全部来自B站。
开始之前先初始化一个vue项目。
PC端使用http-flv协议,移动端使用hls协议
先说下为什么要这样做,因为使用http-flv协议,延时能控制在2s左右,而是用hls,按Apple官方的说法,延时最好10s左右。那么如果项目中追求用户体验的话,PC端的优化就可以从这方面入手。
安装依赖包:
1 | npm install --save flv.js |
按照文档开始使用:
1 | <!--flvplayer--> |
从B站抓取PC端直播连接,填入指定位置即可。
查看效果(chrome浏览器,IE、QQ浏览器均无异常):
关于使用hls协议获取数据流播放的方式,在下面一起讲。
PC和移动端都使用hls协议
目前大多数移动设备都原生支持这种方式播放,PC的话使用一个插件也能达到同样的效果。主要起作用的是一个后缀为.m3u8
的文件。大致用法如下:
1 | <video src="yourM3u8File.m3u8"></video> |
那么问题又来了,播放的原理是什么,为什么这种方式延时会高呢?
这个m3u8文件实际上存着的是一套切片规则,在这里不对这套规则做详细介绍,有兴趣的自行查阅资料。可以简单理解为里面规定了视频如何进行分片,切割为一个个ts文件,一次发送几个数据片。而延时的高低,也是由这个m3u8决定的,假设一次发送3个数据片,一个数据片的播放时长为3s,则延时为9s。
移动端
直接使用最原始的方法,抓取m3u8文件:
在PC假装移动端在B站是无法播放的,但是可以抓取到请求。组件代码如下:
1 | <template> |
测试结果为ios设备能正常播放,ios8会自动全屏播放,浏览器上都无法播放,android设备也无法正常播放。
PC端
为了使PC也支持这种播放方式,我使用了vue-video-player
+ videojs-contrib-hls.js
,vue-video-player本质上是封装了videojs。
1 | npm install vue-video-player --save |
在main.js中引入:
1 | import VueVideoPlayer from 'vue-video-player' |
组件如下:
1 | import VueVideoPlayer from 'vue-video-player' |
浏览器正常:
ios设备正常,android设备也正常,不过我使用android模拟器说视频格式不支持。。。
所以到这里,就可以初步确定直播方案了。
总结
按我最近几天的学习,可以初步制定出2套方案:
一套是http-flv+hls:PC端flvjs,移动端使用videojs+videojs-contrib-hls.js。
另一套是直接使用hls:PC和移动端都使用videojs+vvideojs-contrib-hls.js。
前者的体验在一定程度上优于后者,主要体现在PC端上,flvjs延时更小。
还有一种方法是接入第三方播放器,不过要收费,阿里的腾讯的,不展开写了。