CSDN话题挑战赛第2期
参赛话题:前端技术分享

目录:

  • ✨✨✨前言
  • ✨✨✨前置准备
  • ✨✨✨概述
  • ✨✨✨实现过程及代码
  • ✨✨✨效果展示
  • ✨✨✨资料源
  • ✨✨✨github链接

✨✨✨前言

这是我模仿B站所写项目遇到的第二个很有挑战性的部分,网上的资料比较缺乏,还是大佬室友换了个关键词才搜到比较有用的资料hh。

之前没有写过视频相关的项目,所以视频相关的API都十分陌生。从最开始的一无所知,一步步查资料,理解代码,进行修改,解决代码,最后实现的时候感觉非常有成就感。

网上能找到的相关插件是用angular.js实现(现在基本被vue,react替代),跟我使用技术栈冲突,无法直接引用插件,而且很多技术细节没有文字解释,阅读比较困难。所以写下这篇博客,方便自己重看代码,同时也希望能帮到在实现这一功能受阻的程序猿们o( ̄▽ ̄)ブ

✨✨✨前置准备

  • 对VUE,vite框架,hls.js插件有基本的掌握
  • 对同步异步,promise有基本的了解
  • 熟悉vue3-video-play源代码 以及video相关API
  • 了解canvas画布的使用

✨✨✨概述

整个过程大致可分成5步:

1.预处理,创建一个video标签,视频源和当前视频源一致,并监听canplay事件

2.canplay事件触发时,将整个视频划成若干段,对于每一段,创建一个canvas画布,并修改video的currentTime

3.利用监听函数和promise函数,保证视频截图成功绘制到canvas画布上

4.将canvas转为blob,并用一个数组将其存下来,预处理完成

5.当鼠标悬浮在进度条上时,根据其位置展示对应缩略图

✨✨✨实现过程及代码

一、

本来是想在函数里创造video标签的,但我将hls.js插件初始化设计在Mounted时期,所以就直接在HTML中添加了。

<video id="Vvideo" ref="Vvideo" src="https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8" controls="true"preload="auto" crossOrigin="anonymous" width="400" height="200" v-show="false">您的浏览器不支持 video 标签。
</video>

ngx-thumbnail-video插件监听的是loadeddata,但我尝试的时候发现这样canvas只绘制出黑屏,所以我监听canplay事件,但canplay事件在视频准备好后会一直触发,这好解决,只需要在触发后立刻移除监听函数就可。

const preloadVideoThumbs = () => {state.Vvideo.addEventListener('canplay', setFrontEndPreload);
}
const setFrontEndPreload = async () => {state.Vvideo.removeEventListener('canplay', setFrontEndPreload);// 接下来代码见后文二~四
}

二、

根据自己的需求设置间隔,不过太长太短都不好,太长会导致用户点击后与预览图很可能不一致,太短会导致图片过多从而占用内存较大,我这里设置的3

for (let i = 0; i <= state.Vvideo.duration; i += 3) {let canvas = document.createElement("canvas");const context = canvas.getContext('2d');state.Vvideo.currentTime = i;//接下来代码见后文三
}

三、

这里需要等到 currentTime 对应帧 canplay 后再进行绘制,否则会导致黑屏。但addEventListener是异步操作,等到事件触发时currentTime 就变为最后一个循环的 currentTime ,这显然不是我们想要的。
namo,闭包能解决问题吗?答案是不能,闭包就无法避免currentTime 设置后立刻绘制。

namo 我们能否强制让 addEventListener变成同步呢,promise能解决这个问题.
new promise本身是同步的,只有当遇到resolve / reject 时才会结束,否则将一直阻塞,我们可以将resolve 函数设置在被监听事件的末尾,这样就能达到目的了

await new Promise(function (rsv) {const event = function () {context?.drawImage(state.Vvideo, 0, 0, 300, 150);//代码见后文四state.Vvideo.removeEventListener('canplay', event);rsv(null);};state.Vvideo.addEventListener('canplay', event);});

四、

将绘制出来的canvas转为img图片有两种,toDataURL和toBlob两种,网上实现视频预览这一部分大多都是前者,但我查到的资料了解到toBlob更优,详见博客链接:
https://qa.1r1g.com/sf/ask/3855198931/

canvas.toBlob(function (blob) {state.Thumbnails.push(URL.createObjectURL(blob as Blob));
}, "image/jpeg");

五、

若当前帧已经加载出来,则显示当前帧,否则显示loading。namo如何判断当前帧是否加载完成呢?
我们可以将当前帧应该在数组中位置与数组大小进行比较,若小于,则加载完成。

<img class="d-slider__img"  ref="refImg"   :style="{ left: state.hoverImgLeft }"
:src="state.imgIndex<props.Thumbnails.length? props.Thumbnails[state.imgIndex]:state.loadingImg"
alt="图片加载失败">

细节处理,防止缩略图显示在边框之外

const mousemoveHandle = (ev: MouseEvent) => {if (!props.hover) return;let val = getPosition(ev);emits('onMousemove', ev, val);state.hoverPosition = val;if (props.vertical) return;state.imgIndex=(val*props.totalTimeNumber);state.imgIndex/=3;state.imgIndex=~~state.imgIndex;//获取domlet refSliderEl = (refSlider.value as HTMLButtonElement);// 提示宽的一半宽度let refImgWidth = (refImg.value as HTMLButtonElement).clientWidth / 2;let movePositon = ev.clientX - refSliderEl.getBoundingClientRect().left;// 如果当前往左的偏移量大于提示框宽度if (movePositon < refImgWidth) {state.hoverImgLeft = (refImgWidth - movePositon) + 'px'} else if ((refSliderEl.clientWidth - movePositon) < refImgWidth) {// 如果当前往右的偏移量大于提示框宽度  (总宽度-当前移动位置)< Img一半的宽度state.hoverImgLeft = (refSliderEl.clientWidth - movePositon) - refImgWidth + 'px'} else {state.hoverImgLeft = '50%'}}

✨✨✨效果展示

截图

视频(加载有些小满,请稍等一下~)

✨✨✨资料源

vue3-video-play:https://blog.csdn.net/xdlumia/article/details/11986500

ngx-thumbnail-video:https://levelup.gitconnected.com/build-youtube-like-stylish-video-player-with-thumbnail-preview-on-progress-bar-hovered-53b9074acd75

✨✨✨github链接

想要看完整版代码以及页面效果,请移步github哦
https://github.com/Ki-Wi-Berry/bilibili-videos

⛄码字不易,如果觉得对您有帮助的话,麻烦点个免费的赞~⛄

前端视频预览功能的实现相关推荐

  1. C# 实现视频预览功能(附源码)

    C# 实现视频预览功能 最近新同事在项目中遇到一个难题,如何实现本地视频的预览功能? 我首先想到的是利用Emgu CV 来实现此功能. C/C++中用的是Open CV ,为了使其可以用在.net环境 ...

  2. Hikvison对接NVR实现WEB无插件开发包实现前端视频预览(html、vue、nginx代理)

    场景 Vue中预览HIKVSION海康威视的NVR(网络硬盘录像机)中多个通道(摄像机)的视频: Vue中预览HIKVSION海康威视的NVR(网络硬盘录像机)中多个通道(摄像机)的视频_霸道流氓气质 ...

  3. 前端【vue】实现文档在线预览功能,在线预览pdf、word、xls、ppt等office文件

    前端江太公 前端实现文档在线预览功能 最直接的就是使用XDOC 文档云服务 XDOC可以实现预览以DataURI表示的DOC文档,此外XDOC还可以实现文本.带参数文本.html文本.json文本.公 ...

  4. alert()的功能_前端实现简单的图片上传小图预览功能

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

  5. 给FlvDownloader加了一个视频预览的功能

    今天晚上给FlvDownloader加了一个视频预览的功能,内嵌了一个Flv播放器,现在可以一边下一边播放了,功能集成后在使用用上比上个版本的预览功能要方便不少,不用两边拷贝地址了. 并且基本功能都比 ...

  6. 前端ppt\word等等文件实现在线预览功能

    前端ppt\word等等文件实现在线预览功能 方法1:https://view.xdocin.com/view?src=你的文档地址 10天免费 方法2:https://view.officeapps ...

  7. 前端做预览word(docx)功能

    前端做预览word(docx)功能 前端预览word最好的方法就是后端返回url,然后前端利用iframe进行展示了,效果最好,而且还不会出现内容缺失等的问题. 1.后端返回url 前端直接用ifra ...

  8. 大华监控前端实时预览(DHplayer)官方插件

    介绍:采用vue2+大华官方插件DHplaye+rtsp拉流实现前端预览 1.根据官方文档安装引入插件 2.再vue项目中引入插件 import DHPlayer from '@/components ...

  9. 智能媒体管理产品文档转换/预览功能介绍(4)--快速搭建

    摘要: 智能媒体管理提供了 Cloud Native 架构的文档转换/预览服务,本文介绍快速搭建的示例,让您用 DIY 的体验方式实现文档预览功能. 一.导语 智能媒体管理 提供了 Cloud Nat ...

最新文章

  1. Sweeter Than Fiction - Taylor Swift
  2. SAP QM 稳定性研究功能研习系列1 - 稳定性研究总流程
  3. 最短路问题的原始对偶算法形式
  4. c/c++中extern的作用
  5. 程序员职场第二次课笔记 9.9号
  6. AC日记——魔方 洛谷 P2007
  7. [JavaWeb-MySQL]事务的基本介绍
  8. ajax可以发送文件,通过Ajax上传img时如何发送文件信息
  9. SQL SERVER 表最小行的一个纠结问题
  10. 深入理解JVM虚拟机读书笔记——类的加载机制
  11. 金山文字应用技巧两则(转)
  12. 基于nacos搭建springboot 抽取axios
  13. 视频目标检测入门介绍
  14. 【CVPR20超分】Zooming Slow-Mo: Fast and Accurate One-Stage Space-Time Video Super-Resolution
  15. 北斗导航开始提供全球服务;个人所得税 App 已上线
  16. tf.constant(常量)
  17. 21天转型容器实战营(八容器进阶之Kubernetes 应用生命周期原理分析)
  18. Ubuntu14.04配置TFTP服务器
  19. 哈工大机器学习复习笔记(四)
  20. 射频模块(SX1278)

热门文章

  1. 在安卓手机上安装Linux子系统
  2. 建模贴图技巧,用起来6的飞起
  3. canvas中getContext(“2d“) 对象的属性和方法
  4. uevent netlink(KOBJECT_UEVENT)
  5. 【RDMA】RDMA网卡通讯
  6. ibm mq安装配置_在IBM Integration Bus v10和IBM MQ v8之间配置MQ连接
  7. 极品工控插件 iocomp 中 iXYPlotX1配置全面解析
  8. CString、CTime和COleDateTime转换
  9. 实验九.MATLAB数值积分
  10. 计算机配件名称++太平洋,笔记本电脑配件大全