Web Video使用时遇到的一些问题
问题背景
参考文章: 为什么视频网站的视频链接地址是blob?
最近在做一个web大屏项目,其中有很多视频需要同时播放,
每个页面包括8个实时监控视频,再加上1个背景视频,
再加上页面上繁重的dom渲染和css动画,
运行起来巨卡,
好不容易优化了之后,dom没这么卡了,
但视频还是卡的出奇,于是就特地研究了下这块。
同源策略
视频加载为什么会慢?
- 硬件问题:
- 检查一下浏览器运行网页时的任务管理器资源占用值,CPU都飚到七八十的,电脑是真的*
- GPU烂的就把浏览器的硬件加速关了吧,CPU更烂的当我没说
- 渲染策略问题:
- 不该渲染的元素去掉,少加动画
本地视频,不考虑网络问题,
空白页面,不考虑渲染问题,
为什么视频加载会这么慢呢,难道和编码相关吗?
实时视频是以FMP4流的格式传输来的,
后端还提供了其它一些格式的视频流:
关于视频格式问题,实际上到现在也没有弄清楚:
几个搜索关键字:
WebRTC-Streamer RTSP Fetch
但实际上,8个视频从来都没有一齐被加载出来过,
从来都是加载出6个,后面就没音了,
查看控制台,发现8个请求中总是有2个请求没法出去,被挂起了:
然后我才知道同源策略有个路数限制,
就是最多只能同时对一个协议+ip+端口请求6次,
这里实时视频以FMP4流格式进行传输,接口需要一直保持连接,
所以后面再发起的请求就分不到这6个名额了,
- HTTP升级到2.0
- websocket + flv
- nginx代理
Blob Url
搜索关键字: Video Fetch Blob Url
比较奇特的一点就是,这8个实时视频一番折腾后终于请求过来了,
但实时视频要比本地视频流畅的多。
为什么本地视频会这么卡呢?
一开始我以为是视频编码的原因,
于是将MP4类型的视频转换为webm类型的视频,
结果不知道为什么webm视频一跳转就卡住。
其实视频也不是一直很卡,而是和网页视频缓存条一样,时好时坏,
直到我看到这篇博客:
html5 video 视频页面内缓存 - 全量加载方法
重点是,对普通视频,浏览器会播放一会缓冲一会,即局部下载,
我的视频很短,但是会有很多跳转操作,
如果能在一开始就把视频全量加载,就不怕后面局部加载时出现卡顿的情况了,
实现视频全量加载而不是跟挤牙膏一样的方法就是fetch+blob
1 | fetch(url).then(res=>{ |
需要注意的是,我这里使用的是videoJs播放器,
使用blob url加载视频,需要将创建player的option中的type配置成视频对应的编码
1 | let options = { |
IndexedDB对视频进行切片缓存
使用fetch能够一次性加载完blob格式的视频,
但是又出现新的问题:
本地开发时,视频从本地加载,因此速度快,
服务部署后,静态资源远程fetch需要一些时间(3分钟视频需要加载2分钟)
并且每次加载网页都需要重新加载视频
我尝试配置fetch的option中的 cache选项
1 | fetch('./xxx.mp4',{ |
实际上是没有用的,因为:配置仅是告诉服务器客户端期待的回复方式,服务端如果不支持配置的方式的话也是无用的。
对于ico、字体这种小文件,还比较好缓存,视频这么大的文件就不怎么好缓存了。
视频大小:300MB左右
视频长度:2分半
MIME Type:video/mp4
一开始因为不知道有“存储限制”这个东西,
我尝试使用localStorage存储这个300MB大小的视频,
结果把浏览器卡死好几次,
这是因为localStorage有存储限制
于是我想到有 indexedDB 这个东西。
在用b站看视频时,同样是用blob格式fetch的视频数据就非常流畅,
并且打开时会接着上一次播放,
这里使用的也是用户的浏览器缓存。
除了对视频的meta数据和时间帧进行缓存外,有些时候还会对blob格式的视频本身进行缓存: