发布于 

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个名额了,

参考Issues

Blob Url

搜索关键字: Video Fetch Blob Url

比较奇特的一点就是,这8个实时视频一番折腾后终于请求过来了,
但实时视频要比本地视频流畅的多。

为什么本地视频会这么卡呢?

一开始我以为是视频编码的原因,
于是将MP4类型的视频转换为webm类型的视频,
结果不知道为什么webm视频一跳转就卡住。

其实视频也不是一直很卡,而是和网页视频缓存条一样,时好时坏,
直到我看到这篇博客:
html5 video 视频页面内缓存 - 全量加载方法

重点是,对普通视频,浏览器会播放一会缓冲一会,即局部下载,
我的视频很短,但是会有很多跳转操作,
如果能在一开始就把视频全量加载,就不怕后面局部加载时出现卡顿的情况了,

实现视频全量加载而不是跟挤牙膏一样的方法就是fetch+blob

1
2
3
4
5
6
7
8
fetch(url).then(res=>{
if(!res.ok) throw new Error('network response was not ok')
return res.blob()
}).then(blob=>{
const url = URL.createObjectURL(blob)
const sourceDom = document.createElement('source')
video.src = url
})

需要注意的是,我这里使用的是videoJs播放器,
使用blob url加载视频,需要将创建player的option中的type配置成视频对应的编码

1
2
3
4
5
6
7
let options = {
autoPlay:true,
muted:true,
loop:true,
preload:'auto',
type:"video/mp4"
}

IndexedDB对视频进行切片缓存

fetch重请求导致的问题

使用fetch能够一次性加载完blob格式的视频,
但是又出现新的问题:

本地开发时,视频从本地加载,因此速度快,
服务部署后,静态资源远程fetch需要一些时间(3分钟视频需要加载2分钟)
并且每次加载网页都需要重新加载视频

我尝试配置fetch的option中的 cache选项

1
2
3
fetch('./xxx.mp4',{
cache:'no-cache'
}).then(res=>{})

实际上是没有用的,因为:配置仅是告诉服务器客户端期待的回复方式,服务端如果不支持配置的方式的话也是无用的。

对于ico、字体这种小文件,还比较好缓存,视频这么大的文件就不怎么好缓存了。

浏览器存储视频

视频大小:300MB左右
视频长度:2分半
MIME Type:video/mp4

一开始因为不知道有“存储限制”这个东西,
我尝试使用localStorage存储这个300MB大小的视频,
结果把浏览器卡死好几次,
这是因为localStorage有存储限制

于是我想到有 indexedDB 这个东西。

在用b站看视频时,同样是用blob格式fetch的视频数据就非常流畅,
并且打开时会接着上一次播放,
这里使用的也是用户的浏览器缓存。
除了对视频的meta数据和时间帧进行缓存外,有些时候还会对blob格式的视频本身进行缓存: