前端视频预览功能的实现

这篇具有很好参考价值的文章主要介绍了前端视频预览功能的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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


✨✨✨前言

这是我模仿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;
  //获取dom
  let 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


⛄码字不易,如果觉得对您有帮助的话,麻烦点个免费的赞~⛄文章来源地址https://www.toymoban.com/news/detail-402928.html

到了这里,关于前端视频预览功能的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 科大讯飞-鸟类分类挑战赛-测试【1】

    背景: 随着生态环境的不断变化和人类对自然资源的过度开发,世界各地的鸟类数量和种类正在发生着巨大的变化。为了更好地保护鸟类资源,科学家们需要对鸟类进行详细的研究和记录。然而,传统的鸟类观察方法往往需要大量的人力、时间和物力,而且在观察过程中还可

    2024年02月14日
    浏览(26)
  • 智能算法挑战赛决赛题目——初中组

    从 m 个字符中选取字符,生成 n 个符号的序列,使得其中没有 2 个相邻的子序列相同。如从 1,2,3,生成长度为 5 的序列,序列“12321”是合格的,而“12323”和“12123”是不合格。问:已知 m 和 n 都是小于等于 10 的数字,求 m 个不同字符,组成长度n 的序列中,无 2 个相邻相

    2024年02月11日
    浏览(34)
  • 通义千问AI挑战赛赛后反思

    个人理解: 初赛阶段主要聚焦在如何通过 SFT 提升基础模型的代码能力,需要选手基于最新开源的 Qwen 1.8 模型作为基础模型,上分的关键主要通过收集高质量的代码数据提升模型的在Python, JavaScript, Java, Go, C++, Rust六种编程语言的代码生成能力。 比赛要求采用通义千文模型,

    2024年01月21日
    浏览(32)
  • 【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 详细建模方案及代码实现

    (1)建模思路 【2023 年第十三届 MathorCup 高校数学建模挑战赛】A 题 量子计算机在信用评分卡组合优化中的应用 详细建模过程解析及代码实现 【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 详细建模方案及代码实现 【2023 年第十三届

    2024年02月08日
    浏览(36)
  • 【2023 年第十三届 MathorCup 高校数学建模挑战赛】C 题 电商物流网络包裹应急调运与结构优化问题 建模方案及代码实现

    (1)建模思路 【2023 年第十三届 MathorCup 高校数学建模挑战赛】A 题 量子计算机在信用评分卡组合优化中的应用 详细建模过程解析及代码实现 【2023 年第十三届 MathorCup 高校数学建模挑战赛】 B 题 城市轨道交通列车时刻表优化问题 详细建模方案及代码实现 【2023 年第十三届

    2023年04月16日
    浏览(49)
  • 春秋云镜-内网极限挑战赛-Exchange

    看到奖品还有证书,还涉及oscp方面的东西,过来打打 感谢TryHackMe Exchange 是一套难度为中等的靶场环境,完成该挑战可以帮助玩家了解内网渗透中的代理转发、内网扫描、信息收集、特权提升以及横向移动技术方法,加强对域环境核心认证机制的理解,以及掌握域环境渗透中

    2023年04月19日
    浏览(27)
  • 2023mothercup妈妈杯数学建模挑战赛思路

    先占坑,本人于2019年开始接触数学建模,参加了大大小小几十场数学建模比赛。 本次mothercup也会持续陪跑,为大家提供免费的文字思路和视频思路,后续还有代码和参考文章等。 2023年Mathorcup数学建模竞赛A题 (比赛开始后第一时间更新) 2023年Mathorcup数学建模竞赛B题 (比赛

    2023年04月13日
    浏览(42)
  • C4网络技术挑战赛 智慧园区方案分析

    添加链接描述 网络与应用系统多厂商、多平台、多系统,导致IT部门管理运维复杂,效率低下. 统一运维管理? 无线网络与物联网的双网合一? ps: 无线网络 (英语:Wireless network)指的是任何型式的无线电计算机网络,普遍和电信网络结合在一起,不需电缆即可在节点之间相互链

    2024年02月07日
    浏览(35)
  • 2023 CCPC 华为云计算挑战赛 D-塔

    首先先来看第一轮的 假如有n个,每轮那k个 他们的高度的可能性分别为  n 1/C(n,k) n+1 C(n-(k-1+1),1)/C(n,k) n+2 C(n-(k-2+1),2)/C(n,k) n+i C(n-(k-i+1,i)/C(n,k) 通过概率和高度算出第一轮增加的期望 然后乘上m轮增加的高度加上初始高度,就是总共增加的高度 下面是题解写的过程    

    2024年02月11日
    浏览(34)
  • 【聚焦】“饶派杯”XCTF车联网安全挑战赛即将开启!

    为深入贯彻落实国家网络强国和交通强国战略部署,推动智能网联汽车技术与产业发展、加快该领域人才培养、提升行业创新,打造自主可控、自主研发的中国智能网联汽车安全生态体系, 由江西省委网信办、江西省工信厅、上饶市人民政府主办 ,上饶经济技术开发区、上

    2024年02月07日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包