vue项目视频播放器实现进度条拖动

分享一个自己在项目中遇到的实际问题以及解决办法,早期HTML5提供了video标签,在网页中播放视频已经变成一个非常简单的事,只要一个video标签,src属性设置为视频的地址就完事了。由于src指向真实的视频网络地址,我们使用的video播放器在播放视频的时候会发现无法将视频进度进行拖拽。

1.打开b站的视频,在控制台你可以发现这样一个视频链接,那么为什么b站视频链接是blob格式的,就可以拖动视频进度条了呢?

2.其实这个Blob URL也不是什么新技术,国内外出来都有一阵子了,但是网上的相关的文章不多也不是很详细,今天就和大家一起分享学习一下。

Blob和ArrayBuffer

最早是数据库直接用Blob来存储二进制数据对象,这样就不用关注存储数据的格式了。在web领域,Blob对象表示一个只读原始数据的类文件对象,虽然是二进制原始数据但是类似文件的对象,因此可以像操作文件对象一样操作Blob对象。

ArrayBuffer对象用来表示通用的、固定长度的原始二进制数据缓冲区。我们可以通过new ArrayBuffer(length)来获得一片连续的内存空间,它不能直接读写,但可根据需要将其传递到TypedArray视图或 DataView 对象来解释原始缓冲区。实际上视图只是给你提供了一个某种类型的读写接口,让你可以操作ArrayBuffer里的数据。TypeArray需指定一个数组类型来保证数组成员都是同一个数据类型,而DataView数组成员可以是不同的数据类型。

TypedArray视图的类型数组对象有以下几个:

  • Int8Array:8位有符号整数,长度1个字节。
  • Uint8Array:8位无符号整数,长度1个字节。
  • Uint8ClampedArray:8位无符号整数,长度1个字节,溢出处理不同。
  • Int16Array:16位有符号整数,长度2个字节。
  • Uint16Array:16位无符号整数,长度2个字节。
  • Int32Array:32位有符号整数,长度4个字节。
  • Uint32Array:32位无符号整数,长度4个字节。
  • Float32Array:32位浮点数,长度4个字节。
  • Float64Array:64位浮点数,长度8个字节。

Blob与ArrayBuffer的区别是除了,原始字节以外它还提供了mime type作为元数据,Blob和ArrayBuffer之间可以进行转换。

3.要如何解决这个视频拖拽的问题?

视频拖拽进度是通过HTML5的Video API实现的。在HTML5中,可以使用<video>标签来嵌入视频,并通过JavaScript控制视频的播放、暂停、跳转等操作。当你将视频转换为Blob格式的地址时,实际上是将视频文件转换为二进制数据,并生成一个URL地址来访问这个二进制数据。

通过将视频文件转换为Blob URL后,你可以将该URL赋值给<video>标签的src属性,从而让浏览器加载该视频进行播放。此时,浏览器会根据Blob URL加载视频文件的二进制数据,并进行相应的解码和渲染。由于Blob URL直接指向视频文件的二进制数据,因此可以通过改变<video>标签的currentTime属性来控制视频的播放进度。

当你通过拖拽的方式改变视频进度时,实际上是通过修改<video>标签的currentTime属性来改变视频的当前播放时间。浏览器会相应地加载对应时间点的视频数据,并播放相应位置的视频内容。

实战:以Blob URL加载网络视频

现在我们有一个网络视频的地址,怎么能将这个视频地址变成Blob URL是形式呢,思路肯定是先要拿到存储这个视频原始数据的Blob对象,但是不同于input上传可以直接拿到File对象,我们只有一个网络地址。

我们知道平时请求接口我们可以使用xhr(jquery里的ajax和axios就是封装的这个)或fetch,请求一个服务端地址可以返回我们相应的数据,那如果我们用xhr或者fetch去请求一个图片或视频地址会返回什么呢?当然是返回图片和视频的数据,只不过要设置正确responseType才能拿到我们想要的格式数据。

function ajax(url, cb) {
  const xhr = new XMLHttpRequest();
  xhr.open("get", url);
  xhr.responseType = "blob"; // ""|"text"-字符串 "blob"-Blob对象 "arraybuffer"-ArrayBuffer对象
  xhr.onload = function() {
    cb(xhr.response);
  };
  xhr.send();
}

看到responseType可以设置blob和arraybuffer我们应该就有谱了,请求返回一个Blob对象,或者返回ArrayBuffer对象转换成Blob对象,然后通过createObjectURL生成地址赋值给视频的src属性就可以了,这里我们直接请求一个Blob对象。

ajax('video.mp4', function(res){
    const src = URL.createObjectURL(res); 
    video.src = src;
})

用调试工具查看视频标签的src属性已经变成一个Blob URL,表面上看起来是不是和各大视频网站形式一致了,但是考虑一个问题,这种形式要等到请求完全部视频数据才能播放,小视频还好说,要是视频资源大一点岂不爆炸,显然各大视频网站不可能这么干。

解决这个问题的方法就是流媒体,其带给我们最直观体验就是使媒体文件可以边下边播,web端如果要使用流媒体,有多个流媒体协议可以供我们选择。

希望这个方法对大家有用,我也是在项目中遇到了诸如此类的各种问题,打算记录下来和大家一起分享学习,有诸多不对的地方,欢迎评论区指正。