分享一个自己在项目中遇到的实际问题以及解决办法,早期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中,可以使用
通过将视频文件转换为Blob URL后,你可以将该URL赋值给
当你通过拖拽的方式改变视频进度时,实际上是通过修改
实战:以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端如果要使用流媒体,有多个流媒体协议可以供我们选择。
希望这个方法对大家有用,我也是在项目中遇到了诸如此类的各种问题,打算记录下来和大家一起分享学习,有诸多不对的地方,欢迎评论区指正。