原生JS实现视频截图

news2025/1/11 14:01:41

视频截图效果预览

视频截图效果

利用Canvas进行截图

要用原生js实现视频截图,可以利用canvas的绘图功能 ctx.drawImage,只需要获取到视频标签,就可以通过drawImage把视频当前帧图像绘制在canvas画布上。

const video = document.querySelector('video')
const canvas = document.createElement('canvas')
const w = video.videoWidth
const h = video.videoHeight
canvas.width = w
canvas.height = h
const ctx = canvas.getContext('2d')
ctx.drawImage(video, 0, 0, w, h)

接下来,需要把画布转化为图片,canvas提供了两个2D转换为图片的方法:canvas.toDataURL()canvas.toBlob()

canvas.toDataURL(mimeType, qualityArgument)方法

toDataURL可以把图片转换成base64格式的图片,是一个同步方法,使用很简单,在上面已经绘制好画布的基础上,只需要下面一行代码就可以获取到当前视频帧的截图了

const imageUrl = canvas.toDataURL("image/png")
console.log(imageUrl)

toDataURL生成的base64图片
可以看到,它最终生成了一个很长字符串的base64图片地址。

canvas.toBlob(callback, mimeType, qualityArgument)方法

这个方法相比上一个方法的优点是它是异步的,所以有一个callback回调,这个callback回调方法默认的第一个参数就是转换好的blob文件信息,本文也想重点介绍这种方法的使用

先说明一下这个方法的三个参数:

参数类型是否必传说明
callbackFunctiontoBlob()方法执行成功后的回调方法,支持一个参数,表示当前转换的Blob对象
mimeTypeString表示需要转换的图像的mimeType类型。默认值是image/png,还可以是image/jpeg,甚至image/webp(前提浏览器支持)等
qualityArgumentNumber表示转换的图片质量。范围是0到1。由于Canvas的toBlob()方法转PNG是无损的,因此,此参数默认是没有效的,除非,指定图片mimeType是image/jpeg或者image/webp,此时默认压缩值是0.92

使用写法如下:

canvas.toBlob((blob) => {
	console.log(blob)
}, 'image/png', 0.92)

可以看到方法执行得到的是当前转换的Blob对象
Blob对象
那么剩下的就是要将此Blob对象进一步转化为可供img显示的图片地址。

将Blob对象转化为图片地址

下面介绍三种方法进行转化:

方式一: 通过URL.createObjectURL()方法将Blob转化为URL
canvas.toBlob((blob) => {
	const imageUrl = URL.createObjectURL(blob)
	console.log(1, imageUrl)
}, 'image/jpeg', 1)

如下图所示,转化得到的是一个bold流的图片地址。

blob流图片地址

方式二: 通过FileReader将Blob转化为DataURL
canvas.toBlob((blob) => {
	const reader = new FileReader()
	reader.readAsDataURL(blob)
	reader.onload = () => {
	  const imageUrl = reader.result
	  console.log(2, imageUrl)
	}
}, 'image/webp', 1)

如下图所示,转化得到的是一个base64的图片地址。

base64图片地址

方式三: 通过ajax将Blob上传到服务器
canvas.toBlob((blob) => {
	const formData = new FormData()
    formData.append('file', blob) // 这里的'file'是接口接收参数的字段名,需要根据实际情况改变
    const xhr = new XMLHttpRequest()
    xhr.onload = () => {
      const imageUrl = JSON.parse(xhr.responseText).data // 接口回调参数,需要根据实际情况处理
      console.log(3, imageUrl)
    }
    xhr.open('POST', '/api/upload', true) // '/api/upload'是上传接口,需要根据实际情况改变
    xhr.send(formData)
}, 'image/webp', 1)

由此就会将图片上传到你的文件服务器里,最终可以得到一个你自己文件服务器下对应的图片地址。

toBlob()方法的兼容

首先,toBlob()方法IE9浏览器不支持,因为Blob数据格式IE10+才支持。

然后,对于IE浏览器,toBlob()的兼容性有些奇怪,IE10浏览器支持ms私有前缀的toBlob()方法,完整方法名称是msToBlob()。而IE11+,toBlob()方法却不支持。

但是,我们可以基于toDataURL()方法进行polyfill,性能相对会差一些,JavaScript代码如下:

if (!HTMLCanvasElement.prototype.toBlob) {
  Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
    value: function (callback, type, quality) {
      var canvas = this
      setTimeout(function() {
        var binStr = atob( canvas.toDataURL(type, quality).split(',')[1] )
        var len = binStr.length
        var arr = new Uint8Array(len)

        for (var i = 0; i < len; i++) {
          arr[i] = binStr.charCodeAt(i)
        }

        callback(new Blob([arr], { type: type || 'image/png' }))
      })
    }
  })
}

注意事项

使用外部链接播放视频的话需要在视频标签上设置允许跨域的处理,添加属性crossOrigin='anonymous'即可,

<video className="videoTag" crossOrigin='anonymous' controls>
     <source src="https://www.w3school.com.cn/example/html5/mov_bbb.mp4" type='video/mp4' />
</video>

或者,在js里处理

const video = document.querySelector(".videoTag")
video.setAttribute('crossOrigin', 'anonymous')
video.load()

否则会报以下错误:
跨域报错

完整封装示例

最后,给出一个利用toBlob进行视频截图,最终获取base64图片地址的封装方法,代码示例如下:

function getBase64ByVideo(video) {
	const canvas = document.createElement("canvas")
    const w = video.videoWidth
    const h = video.videoHeight
    canvas.width = w
    canvas.height = h
    return new Promise((resolve, reject) => { // 由于toBlob方法是异步的,所以这里用Promise
      const ctx = canvas.getContext('2d')
      ctx.drawImage(video, 0, 0, w, h)
      canvas.toBlob((blob) => {
        // 通过FileReader将Blob转化为DataURL
        const reader = new FileReader()
        reader.readAsDataURL(blob)
        reader.onload = () => {
          const imageUrl = reader.result
          resolve(imageUrl)
        }
      }, 'image/webp', 1) // 根据需要可以自行配置这里的两个参数
    })
}

调用方法:

const videoTag = document.querySelector(".videoTag")
const dataUrl = await getBase64ByVideo(videoTag)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1203668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

若依系统富文本框上传图片报错!

报错如下&#xff1a; 原因&#xff1a;如图&#xff0c;富文本路径中存在 / 字符&#xff0c;导致上传出错。 解决方案&#xff1a;将富文本框内容在前端进行加密&#xff0c;后端再解密。 前端&#xff1a; 安装 crypto-js 插件 npm install crypto-js 创建工具类 :在 sr…

postswigger 靶场(CSRF)攻略-- 1.没有防御措施的 CSRF 漏洞

靶场地址&#xff1a; What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy (portswigger.net)https://portswigger.net/web-security/csrf 没有防御措施的 CSRF 漏洞 题目中已告知易受攻击的是电子邮件的更改功能&#xff0c;而目…

【正点原子STM32连载】 第五十二章 图片显示实验摘自【正点原子】APM32F407最小系统板使用指南

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html## 第五…

c语言从入门到实战——初识指针

初识指针 前言1. 内存和地址1.1 内存1.2 究竟该如何理解编址 2. 指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 如何拆解指针类型2.2.3 解引用操作符 2.3 指针变量的大小 3. 指针变量类…

Sprint Boot 学习路线 6

测试 Spring提供了一组测试工具&#xff0c;可以轻松地测试Spring应用程序的各个组件&#xff0c;包括控制器、服务、存储库和其他组件。它具有丰富的测试注释、实用程序类和其他功能&#xff0c;以帮助进行单元测试、集成测试等。 JPA测试 Spring JPA&#xff08;Java Pers…

开放领域对话系统架构

开放领域对话系统是指针对非特定领域或行业的对话系统&#xff0c;它可以与用户进行自由的对话&#xff0c;不受特定领域或行业的知识和规则的限制。开放领域对话系统需要具备更广泛的语言理解和生成能力&#xff0c;以便与用户进行自然、流畅的对话。 与垂直领域对话系统相比…

从单服务设计看SLA保证

文章首发公众号&#xff1a;海天二路搬砖工 0. 引言 在微服务架构中&#xff0c;谈到SLA保证&#xff0c;我们更多是从宏观的角度来需求解决方案。比如&#xff0c;通过合理服务拆分来增加系统整体的可维护性&#xff1b;通过多实例部署来保证系统的灾备。但是单个服务是可靠…

2023NewStarCTF

目录 一、阳光开朗大男孩 二、大怨种 三、2-分析 四、键盘侠 五、滴滴滴 六、Include? 七、medium_sql 八、POP Gadget 九、OtenkiGirl 一、阳光开朗大男孩 1.题目给出了secret.txt和flag.txt两个文件&#xff0c;secret.txt内容如下&#xff1a; 法治自由公正爱国…

【JVM】类加载器 Bootstrap、Extension、Application、User Define 以及 双亲委派

以下环境为 jdk1.8 两大类 分类成员语言继承关系引导类加载器bootstrap 引导类加载器C/C无自定义类加载器extension 拓展类加载器、application 系统/应用类加载器、user define 用户自定义类加载器Java继承于 java.lang.ClassLoader 四小类 Bootstrap 引导类加载器 负责加…

故障演练 | 微服务架构下如何做好故障演练

前言 微服务架构场景中&#xff0c;应用系统复杂切分散。长期运行时&#xff0c;局部出现故障时不可避免的。如果发生故障时不能进行有效反应&#xff0c;系统的可用性将极大地降低。 什么是故障演练 故障演练是指模拟生产环境中可能出现的故障&#xff0c;测试系统或应用在…

软考网络工程师知识点总结(二)

目录 21、海明码--差错控制 22、CRC循环冗余校验码 23、网络时延的计算 24、根据距离选择传输介质 25、多模光纤和单模光纤的区别 26、CSMA/CD协议 27、以太网帧结构 28、以太网类型及传输介质的选择 29、交换式以太网&#xff08;交换机&#xff09; 30、VLAN虚拟局…

Rust编程中的线程间通信

1.消息传递 为了实现消息传递并发&#xff0c;Rust 标准库提供了一个 信道&#xff08;channel&#xff09;实现。信道是一个通用编程概念&#xff0c;表示数据从一个线程发送到另一个线程。 可以将编程中的信道想象为一个水流的渠道&#xff0c;比如河流或小溪。如果你将诸如…

【C++ 学习 ㊱】- 智能指针详解

目录 一、为什么需要智能指针&#xff1f; 二、智能指针的原理及使用 三、auto_ptr 3.1 - 基本使用 3.2 - 模拟实现 四、unique_ptr 4.1 - 基本使用 4.2 - 模拟实现 五、shared_ptr 5.1 - 基本使用 5.2 - 模拟实现 六、weak_ptr 6.1 - shared_ptr 的循环引用问题 …

【Python小程序】求解2 * 2矩阵的逆矩阵

一、内容简介 使用Python求解2 * 2矩阵的逆矩阵。 二、求解方法 我们使用邻接矩阵法来求解2 * 2矩阵的逆矩阵。 det(A): 矩阵A的行列式 adj(A): 矩阵A的邻接矩阵 对于2*2矩阵A 我们有 三、Python代码 基于上述求解方法&#xff0c;我们可以写出Python代码如下&#xff…

行情分析——加密货币市场大盘走势(11.13)

大饼上涨太快&#xff0c;又开始震荡&#xff0c;但上不去&#xff0c;所以目前来看差不多要做回踩动作&#xff0c;入场空单性价比较高。而且从MACD日线来看&#xff0c;也是进入空头趋势&#xff0c;RSI&#xff08;14&#xff09;也是进入了超买区间&#xff0c;值得入手空单…

乡镇村污水处理智慧水务智能监管平台,助力污水监管智慧化、高效化

一、背景与需求 随着城市化进程的加速&#xff0c;排放的污水量也日益增加&#xff0c;导致水污染严重。深入打好污染防治攻坚战的重要抓手&#xff0c;对于改善城镇人居环境&#xff0c;推进城市治理体系和治理能力现代化&#xff0c;加快生态文明建设&#xff0c;推动高质量…

拼多多商品详情API接口接入流程如下:

拼多多商品详情API接口可以用于获取拼多多商品的具体信息&#xff0c;包括商品ID、商品名称、价格、销量、评价等。以下是使用拼多多商品详情API接口的步骤&#xff1a; 进入拼多多开放平台&#xff0c;注册并登录账号。在开放平台页面中&#xff0c;找到“商品详情”或“商品…

基于SSM+Vue的电子商城的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

基因检测技术的发展与创新:安全文件数据传输的重要作用

基因是生命的密码&#xff0c;它决定了我们的身体特征、健康状况、疾病风险等。随着基因检测技术的高速发展&#xff0c;我们可以通过对基因进行测序、分析和解读&#xff0c;更深入地认识自己&#xff0c;预防和治疗各种遗传性疾病&#xff0c;甚至实现个性化医疗和精准健康管…

动态调整学习率Lr

动态调整学习率Lr 0 引入1 代码例程1.1 工作方式解释 2 动态调整学习率的几种方法2.1 lr_scheduler.LambdaLR2.2 lr_scheduler.StepLR2.3 lr_scheduler.MultiStepLR2.4 lr_scheduler.ExponentialLR2.2.5 lr_scheduler.CosineAnnealingLR2.6 lr_scheduler.ReduceLROnPlateau2.7 …