您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JS截取视频第一帧

时间:2019-08-29 17:53:25  来源:  作者:

当视频能够预览并上传后,非要来一张视频第一帧的截图贴上,第一帧是黑的怎么办,下一帧。

一、文件上传

使用<input type="file">上传,change事件作为预览video的src的触发条件 新鲜源码:

<video controls width="700" height="300" src="" id="video"></video>
<input type="file" id="input" hidden />
<button id="fileBtn">点击上传视频</button>

二、canvas截取图片

关于截取或者处理图片/视频/富文本编辑器,canvas是一个非常nice的选择。

  1. 创建画布canvas或在html中直接写入。
var canvas = document.createElement('canvas');
  1. 创建基于canvas的绘图环境
var ctx = canvas.getContext('2d');

附 Q&A:

  • 什么是绘图环境?

网络上的常规理解是“在准备画布后,需要一些‘染料、画笔、绘图工具’的准备工作。” 比较官方的说话是返回canvas的上下文环境, 说人话是'你能够更好的操作你的canvas'。

  • 关于getContext('2d')的参数

方法中的2d参数目前可以理解为是固定参数,表示想要一个二维绘制环境。虽然大家都认为有2d自然应该有3d,然而实际上本身设计时也是这么考虑的,不过大家有点等不起了,所以都去选择webGL了。 webGL是啥?浏览器端借助系统显卡进行 3D 绘图。这是另一个故事了(IE别想了)。

  • 关于canvas.getContext('2d')的返回值

返回一个CanvasRenderingContext2D对象,也就是上文所说的能够支持绝大多数对画布的操作。

  1. 在canvas上绘制图片
 // ctx.drawImage(file,sx,sy,swidth,sheight,x,y,width,height);
 ctx.drawImage(this, 0, 0, swidth, sheight);

在不需要剪裁的情况下,使用上述参数即截取操作file的全部,绘制到canvas上

关于参数(w3school) |参数 | 描述 | | :-------: |:-------------:| |file|规定要使用的图像、画布或视频。 |sx|可选。开始剪切的 x 坐标位置。 |sy|可选。开始剪切的 y 坐标位置。 |swidth|可选。被剪切图像的宽度。 |sheight|可选。被剪切图像的高度。 |x|在画布上放置图像的 x 坐标位置。 |y|在画布上放置图像的 y 坐标位置。 |width|可选。要使用的图像的宽度。(伸展或缩小图像) |height|可选。要使用的图像的高度。(伸展或缩小图像)

  1. 将canvas导出成图片放入src
var src = canvas.toDataURL('image/jpeg');

关于toDataURL()方法。将canvas的内容导出

canvas.toDataURL(type, encoderOptions);

type: 图片格式,默认image/jpeg, encoderOptions:图片质量,取值范围为0到1,默认0.92。 返回值:包含 data URI 的DOMString,也就是base64格式。

三、截取视频第一帧

上传文件OK,用canvas截取OK,怎么找第一帧呢?(啥时候开始截取呢?)

当然是多媒体的事件来触发。 关于video的事件非常多(全部事件),这里只讨论能够影响到截取到第一帧的各个事件。

 video.addEventListener('loadeddata', consoleString.bind(video, 'loadeddata')) // 当前帧加载完毕
 video.addEventListener('loadedmetadata', consoleString.bind(video, 'loadedmetadata')) // 视频元数据加载完毕
 video.addEventListener('canplay', consoleString.bind(video, 'canplay')) // 视频缓冲能够开始播放
 video.addEventListener('timeupdate', consoleString.bind(video, 'timeupdate')) // 播放位置发生改变时
 video.addEventListener('play', consoleString.bind(video, 'play')) // 开始播放时
 video.addEventListener('waiting', consoleString.bind(video, 'waiting')) // 要播放下一帧而需要缓冲时
 
 function consoleString(string) {
 console.log(string)
 }
// 执行结果
// timeupdate 
// loadedmetadata 
// loadeddata 
// canplay 
// play(开始播放)
// 没有waiting, 因为视频较小不需要缓冲
  • 根据顺序,第一个被触发的竟然是timeupdate事件,按设想来说,最先执行的应该是loadedmetadata,元数据加载完毕。 关于这一点,在MDN上没有明确的说明,但是可以推理一下:

当currentTime更新时会触发timeupdate事件

来源:MDN

loadedmetadata的元数据恰好是指时长、尺寸(仅视频)以及文本轨道,也就是说在video未定义的时候currentTime是NaN或NULL,当元数据中时长加载完毕后,currentTime更新至0,因此触发。

结论:虽然最先触发,但是此时视频文件尚未加载,截取的是canvas的无内容本身。 注:timeupdate事件根据使用的系统不同,每秒触发4-66次,且由于触发频率高,单位过小(毫秒级别),事件响应需要延迟等原因,无法完全精准的控制。

  • loadedmetadata 上文提到,元数据加载完毕之后即触发,但数据中并不包括视频文件本身。 结论:如果视频文件较大,加载时间较长,仍然无法截取到已加载的第一帧。 补充:通过URL.createObjectURL()方法能够基本做到无察觉,但并不保险
  • loadeddata 当前帧数(第一帧)加载完毕触发,没毛病。 结论:可用。 补充:万一第一帧是黑屏想用下一帧怎么办,对不起,余下帧数加没加载完不在它的考虑范围之类,这个事件不管。
  • canplay 视频能够开始播放时触发,也就是根据上传的视频帧数决定加载多少帧(24/25/30/60等等)后满足播放画面后触发。 总结:因为加载相对于loadeddata的事件来说更多(多一丢丢),总体可行。 补充:通过控制currentTime可以满足(但不可能是第二帧那么准确),可以看做“当前播放帧”。
  • play 开始播放时才会触发,和上传快速截取的需求不是很符合。
  • waiting 已播放但下一画面没缓冲好时触发,适合插播小广告。

文件、方法、事件都OK了。截就完事儿了。

 video.addEventListener('loadeddata', function (e) {
	 canvas.width = this.videoWidth
	 canvas.height = this.videoHeight
	 width = this.videoWidth
	 height = this.videoHeight
	 ctx.drawImage(this, 0, 0, width, height);
	 var src = canvas.toDataURL('image/jpeg');
	 img.src = src; 
	 // var currentTime = this.currentTime
	 // duration = this.duration
	 // var fps = duration / 30
		
 })


Tags:JS   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
前言几乎所有.NET序列化程序的实现基础都是反射。下列代码是Newtonsoft.Json的实现:protectedvirtualJsonPropertyCreateProperty(MemberInfomember,MemberSerializationmemb...【详细内容】
2021-12-28  Tags: JS  点击:(2)  评论:(0)  加入收藏
前言JDBC访问Postgresql的jsonb类型字段当然可以使用Postgresql jdbc驱动中提供的PGobject,但是这样在需要兼容多种数据库的系统开发中显得不那么通用,需要特殊处理。本文介绍...【详细内容】
2021-12-23  Tags: JS  点击:(13)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  Tags: JS  点击:(23)  评论:(0)  加入收藏
前言前几天有粉丝在群里问了一个json文件处理的问题。看上去他只需要follower和ddate这两个字段下的对应的值。我们知道json是一种常见的数据传输形式,所以对于爬取数据的数...【详细内容】
2021-12-07  Tags: JS  点击:(40)  评论:(0)  加入收藏
作者:前端进阶者来源:前端进阶学习交流一、前言 我们经常在网页上 ,游戏界面加载时会看到加载进度条的效果,我们往往会以为这些加载进度条的效果,很难实现。今天教大家JS+CSS结合...【详细内容】
2021-11-05  Tags: JS  点击:(45)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  Tags: JS  点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  Tags: JS  点击:(58)  评论:(0)  加入收藏
利用JS的CryptoJS 3.x和PHP的openssl_encrypt,openssl_decrypt实现AES对称加密解密,由于需要两种语言对同一字符串的操作,而CryptoJS 的默认加密方式为“aes-256-cbc”,PHP端也...【详细内容】
2021-09-16  Tags: JS  点击:(79)  评论:(0)  加入收藏
作者:JShaman.com:w2sft内容预告:本文将实例讲解以下JS代码混淆加密技术:方法名转义和转码、成员表达式转IIFE、函数标准化、数值混淆、布尔型常量值混淆、二进制表达式转为调用...【详细内容】
2021-09-03  Tags: JS  点击:(82)  评论:(0)  加入收藏
Web 浏览器日益强大,网站和 Web 应用程序的复杂性也在增加。几十年前需要超级计算机的操作现在可以在智能手机上运行,其中之一就是人脸检测。检测和分析人脸的能力非常有用,因...【详细内容】
2021-08-20  Tags: JS  点击:(105)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === &#39;a&#39;) { b = true} else { b = false}// goodb = a === &#39;a&#39;2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(6)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(20)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(35)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(36)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(40)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== &#39;&#39;) { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(51)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条