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端如果要使用流媒体,有多个流媒体协议可以供我们选择。

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

  • 34
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue Video.js是一个基于Vue.js和Video.js的HTML5视频播放器组件,可以帮助我们快速搭建一个美观实用的视频播放器。在Vue Video.js中,要实现进度条拖动,需要做以下几个步骤: 1.首先,在Vue Video.js中,可以通过vjs-player组件来实现视频播放功能,我们需要给这个组件添加ref属性,以便在后面使用。 2.在vjs-player的mounted生命周期中,我们可以通过this.$refs.player来获取到video.js的player对象,然后通过player.on方法来监听时间变化事件。 3.在监听事件中,可以获取到当前播放的时间和视频总时长,从而计算出当前进度条的位置。同时,也可以监听进度条的mousedown和mousemove事件,来实现进度条拖动的功能。 4.最后,在进度条拖动结束的时候,需要通过player.currentTime()方法来设置视频的当前播放时间。 下面是相关代码片段: ```vue <template> <div> <vjs-player ref="player" :options="playerOptions"></vjs-player> <div class="progress-bar-wrap"> <div class="progress-bar" ref="progressBar" @mousedown="onProgressBarMouseDown($event)"> <div class="progress-bar-inner" :style="{width: progressWidth}"></div> <div class="progress-bar-thumb" :style="{left: progressWidth}"></div> </div> </div> </div> </template> <script> export default { data() { return { playerOptions: { autoplay: false, controls: true, sources: [{ src: 'https://example.com/path/to/video.mp4', type: 'video/mp4' }] }, progressWidth: 0, isDragging: false } }, mounted() { const player = this.$refs.player.$player player.on('timeupdate', () => { const currentTime = player.currentTime() const duration = player.duration() this.progressWidth = `${(currentTime / duration) * 100}%` }) document.addEventListener('mousemove', this.onDocumentMouseMove) document.addEventListener('mouseup', this.onDocumentMouseUp) }, beforeDestroy() { document.removeEventListener('mousemove', this.onDocumentMouseMove) document.removeEventListener('mouseup', this.onDocumentMouseUp) }, methods: { onProgressBarMouseDown(event) { this.isDragging = true this.onDocumentMouseMove(event) }, onDocumentMouseMove(event) { if (!this.isDragging) return const progressBar = this.$refs.progressBar const rect = progressBar.getBoundingClientRect() const progressWidth = ((event.clientX - rect.left) / rect.width) * 100 this.progressWidth = `${Math.min(Math.max(progressWidth, 0), 100)}%` }, onDocumentMouseUp() { if (!this.isDragging) return const player = this.$refs.player.$player const duration = player.duration() player.currentTime(duration * (parseInt(this.progressWidth) / 100)) this.isDragging = false } } } </script> <style> .progress-bar-wrap { width: 100%; height: 8px; background-color: #f2f2f2; } .progress-bar { position: relative; width: 100%; height: 100%; cursor: pointer; } .progress-bar-inner { position: absolute; top: 0; left: 0; height: 100%; background-color: #00bfff; } .progress-bar-thumb { position: absolute; top: -5px; left: -8px; width: 16px; height: 16px; border-radius: 50%; background-color: #00bfff; } </style>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值