JavaScript截取视频第一帧

一、背景

在企业资料的开发中,除了涉及到视频上传之外,还需要使用视频中的第一帧或者或许几帧作为视频封面展示。

产生的问题:

因此,JS截取视频第一帧的难点就此诞生,但是查阅了资料发现,网上提供的资料无外乎俩种,第一种是 wasm + ffmpeg 配合后端去截取,第二种是JS自行截取。优缺点也是显而易见的,第一种,配合成本比较高,而且不是很灵活;第二种可以满足一般条件下的使用,但是会有兼容问题(IE再见)以及截取黑屏的问题。

二、wasm + ffmpeg

这种方式优缺点也是显而易见的,配合成本比较高,而且会造成web内存的急剧飙升,但是支持的视频种类已经截取的帧数是很灵活的;由于涉及到服务端,具体可以参考 wasm + ffmpeg 截取视频。

三、JavaScript 前端截取

这里前端截取的话就需要了解 video、canvas 标签的兼容性和响应事件了。而且对IE可能不是那么友好。

1. canvas的知识这里不做过多补充,下面主要看一下video标签的响应事件有哪些:

执行结果

根据顺序,第一个被触发的竟然是 timeupdate 事件,按设想来说,最先执行的应该是 loadedmetadata,元数据加载完毕。关于这一点,在MDN上没有明确的说明,但是可以推理一下:当 currentTime 更新时会触发 timeupdate 事件

结论:虽然最先触发,但是此时视频文件尚未加载,截取的是 canvas 的无内容本身。注:timeupdate 事件根据使用的系统不同,每秒触发4-66次,且由于触发频率高,单位过小(毫秒级别),事件响应需要延迟等原因,无法完全精准的控制。loadedmetadata 上文提到,元数据加载完毕之后即触发,但数据中并不包括视频文件本身。结论:如果视频文件较大,加载时间较长,仍然无法截取到已加载的第一帧。补充:通过 URL.createObjectURL()方法能够基本做到无察觉,但并不保险。

loadeddata 当前帧数(第一帧)加载完毕触发,没毛病。结论:可用。补充:万一第一帧是黑屏想用下一帧怎么办,对不起,余下帧数加没加载完不在它的考虑范围之类,这个事件不管。

canplay 视频能够开始播放时触发,也就是根据上传的视频帧数决定加载多少帧(24/25/30/60等等)后满足播放画面后触发。总结:因为加载相对于 loadeddata的事件来说更多(多一丢丢),总体可行。补充:通过控制 currentTime可以满足(但不可能是第二帧那么准确),可以看做“当前播放帧”。

play 开始播放时才会触发,和上传快速截取的需求不是很符合。

waiting 已播放但下一画面没缓冲好时触发,适合插播小广告。

2. 了解上面的响应事件之后,让我们来看一下接下来截取操作:

上面的的结果是什么呢?

可以看到已经很成功的截取到了视频的第一帧,那么到此阶段,其实已经基本实现了需求,但是图片是否是有效的,这个还未可知,所以需要我们进一步去判断。

3. 第一帧是否有效

其实,截取到的第一帧图片,有些时候由于视频的质量不佳或者一些其他因素影响,截取到的图片往往不是很符合预期,一直与会出现纯黑的图片,透明图片,白色图片等等无效图片。因此,我们需要进行一下图片有效性的识别。

那么,怎么去识别图片的有效性呢?

这时候,你就需要认识一个新属性了:Uint8ClampedArrayUint8ClampedArray(8位无符号整型固定数组) 类型化数组表示一个由值固定在0-255区间的8位无符号整型组成的数组;如果你指定一个在 [0,255] 区间外的值,它将被替换为0或255;如果你指定一个非整数,那么它将被设置为最接近它的整数。(数组)内容被初始化为0。一旦(数组)被创建,你可以使用对象的方法引用数组里的元素,或使用标准的数组索引语法(即使用方括号标记)。

如果对 Uint8ClampedArray 感兴趣,可以异步这里进一步研究 Uint8ClampedArray。

你是不是发现了什么?0~255这个是不是常见的数值,颜色的十六进制对应的数值。好,那么,接下来就是按照我们所思考好的去实现,看看是不是这么一个原理。

代码是实现了,那么结果呢,我这里分别使用白色图片,透明图片,黑色图片来对照一下,拿到的结果究竟是不是和我们所想象的一直的:

首先我们来看一下透明图片:

可以看到,结果数组里面,全部是 0;

白色图片:

哎呦,全是255,那么黑色就应该全是0了,别急,让我们看一下

黑色图片:

出现了意想不到的数字,238,这是偏向255白色的色值,为什么会这样呢?其实是因为白色和透明色没有过度,而黑色是过度的,就是在canvas绘制的时候会出现这种问题,但是是可以忽略不计的。

知道了这三者的色值,那么接下来的判断也就好办了,直接在加一个条件就好了

为什么是200 和 0 呢?其实这俩个值你们可以根据实际情况去判断合理范围,200 对应的色值是#c8c8c8,是灰色,0是透明色,所以在这里就判断是无效图片了。只要brr数组里面没有值,就说明是无效图片。

那么实际情况如何呢?再来一张实际的对比图:

可以看到,brr里面是有值的,而且还是大量的,所以这正图片就是有效图片。

4. 最后

JavaScript截取视频第一帧就已经完毕了,如果还想优化就是针对无效图片的时候,使用默认图片展示即可。

四、总结

JavaScript截取视频第一帧,过程比较繁杂,而且涉及到很大量的数据循环,会造成一定的内存增长,但是确确实实能解决这个问题,并且已经已用到了企业资料中,其中使用了一个取巧优化的办法,只有brr数组有一个值被push进去,就直接break,这样可以极大的优化性能。如果大家还有更好的解决办法,可以多多交流!想了解更多编程学习,敬请关注php培训栏目!

js截取视频第一帧_学学javascript如何截取视频第一帧相关推荐

  1. 腾讯视频下载格式_怎么下载腾讯视频

    不管这个腾讯视频好用与否,都有一大批用户,本文播放器家园网小编分享腾讯视频下载格式_怎么下载腾讯视频.腾讯视频时刻为您推荐最新最火的视频,精彩不断随时观看.支持各种画质的下载,没网也能享受高视觉的享受 ...

  2. 腾讯视频下载的视频怎么剪辑_怎样卸载腾讯视频

    腾讯视频影音是一款界面轻松友好,功能全面完善,方便好用,绿色安全,完全免费的.专注视频播放的客户端软件,您可运行腾讯视频影音,在线享受腾讯视频网站内全部免费高清正版视频.腾讯视频可以在线享受丰富多彩的 ...

  3. python 视频剪辑软件_用Python玩转视频剪辑,秀的飞起!

    1 前言 半个月前,后台有个小伙伴问我,如何将视频中的音频提取出来,并且将声音转成文字写入到 word 中,正好接下来的文章要用到百度的语音识别接口. 那么今天就来给大家介绍一个专门用于视频操作的库, ...

  4. python视频提取关键帧_如何使用Python提取视频的关键帧?

    在很多场景下,我们不想或者不能处理视频的每一帧图片,这时我们希望能够从视频中提取出一些重要的帧进行处理,这个过程我们称为视频关键帧提取. 关键帧提取算法多种多样,如何实现主要取决于你对于关键帧的定义. ...

  5. python 视频转场_利用Python 进行短视频的二次创作

    1.目 标 场 景 无论是抖音还是快手等视频平台,一旦一个视频火了后,很多 UP 主都会争先抢后去模仿拍摄或剪辑,然后上传到平台,最后都能带来不错的流量. 对于一般的短视频,完全可以通过裁剪.特效转场 ...

  6. js判断对象为空_在 JavaScript 中如何检查对象为空

    下面的代码片段,用于检查对象是否为空.对于较新的浏览器,你可以使用 ES6 的 "Object.keys".?对于较旧的浏览器,可以安装Lodash库并使用其" isEm ...

  7. js数组查找最接近_在JavaScript数组中找到最小元素的位置

    在JavaScript数组中找到最小元素的位置 注*  之前有篇文章介绍过数据遍历的性能比较: for in 比for loop慢至少20倍 ,这是另外一篇比较数组查找性能的例子,通过对手工/inde ...

  8. js 格式化 java时间格式化_用JavaScript(js)对时间格式化

    可以说是Web项目中不可或缺的一个Javascript类库,它可以帮助你快速的解决客户端编程的许多问题,下面贴出一个用js格式化时间的方法. Date.prototype.format=functio ...

  9. js获取唯一设备码_使用Javascript获取设备的唯一 id_javascript_酷徒编程知识库

    你可以为此目的访问设备的uuid 在Phonegap中你可以使用Cordova设备插件/* Android: Returns a random 64-bit integer (as a string, ...

  10. js微信抢红包脚本代码_基于JavaScript实现微信抢红包功能

    金额随机:额度在0.01和(剩余平均值*2)之间. 0){ let num = scramble(remainAmount,remainPeople); remainAmount = remainAm ...

最新文章

  1. Vista下的程序集缓存卸载方法,也就是C:\Windows\assembly之下的卸载方法
  2. LeetCode Rotate List
  3. python调整数组顺序使奇数位于偶数前面
  4. 维护无后效性的技巧——立即计算代价
  5. php基础教程 第十一步 面向对象补充
  6. Fence(CF-324F)
  7. c++_string与double/int互转
  8. 如何下载火山安卓软件开发平台
  9. linux信号量配合共享内存应用分析(详解)
  10. qt打包安装程序需要先安装其他驱动或者依赖库的解决方案(Setup Factory)
  11. OSChina 周五乱弹 —— 我FFFF……佛慈悲
  12. python 根据word生成ppt_python操作word、ppt的详解
  13. 备份恢复Lesson 08. Using RMAN-Encrypted Backups
  14. 远驱240控制器调整参数_制冷系统高低压压力保护控制器工作原理与设定方法
  15. spring技术详解
  16. 服务器主板显示ff,主板诊断卡跑FF的原因及检查思路
  17. uniapp 浙政钉埋点——小程序
  18. 如何拿到当月的天数?
  19. Java方法的概述、格式说明和调用
  20. VUE3中,使用.env.development和.env.production

热门文章

  1. 应用内悬浮窗适配方案实战
  2. 不使用setPositiveButton 如何让alertdialog消失
  3. 带你搞懂朴素贝叶斯分类算法
  4. win10麦克风直接输出声音_win10系统音频前后同时有声音输出的技巧
  5. VS2017生成可执行程序,执行提示“不是有效的win32应用程序”
  6. 数组添加/扩容和数组缩减
  7. 红色警戒2修改器原理百科(七)
  8. T410i开机显示fan error修复
  9. Oracle 11g客户端网络服务名配置
  10. c++程序员书籍推荐