Electron应用中实现调用外接摄像头并拍照上传
背景
基于Electron
实现的pc端智能验机应用,近期迭代了一个新的功能,需求是通过电脑外接摄像头
对手机屏幕进行拍照
,拍照后需将照片上传
至服务端进行屏幕信息比对,确定被检测屏幕是否为原厂屏。
需求分析
根据上面的需求,分析大概要以下几个步骤。
先实现将摄像头的画面实时展示在页面视频采集区域中;
将摄像头中的视频画面采集一帧成图片并回显;
将生成的图片上传至CDN拿到图片链接;
将图片链接上传到后端接口做处理;
确定了需要以上四个步骤后,接下来一步一步实现。
实现
视频采集
由于
Electron
内置了Chromium
浏览器,该浏览器对各项前端标准都支持得非常好,所以基于 Electron 开发应用不会遇到浏览器兼容性问题。几乎可以在 Electron 中使用所有HTML5
、CSS3
、ES6
标准中定义的API
。
所以基于WebRTC
提供的API
即可获取到摄像头的视频流。
MediaDevices.getUserMedia()
代码如下:
methods: {getUserMedia() {/* 可同时开启video(摄像头)和audio(麦克风) 这里只请求摄像头,所以只设置video为true */navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {/* 使用这个 stream 传递到成功回调中 */this.success(stream)}).catch(function(err) {/* 处理 error 信息 */this.error(error)});}
}
MediaDevices.getUserMedia()
会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream
,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其它轨道类型。
它返回一个 Promise
对象,成功后会resolve
回调一个 MediaStream
对象。若找不到满足请求参数的媒体类型,promise
会reject
回调一个NotFoundError
。
现在已经成功获取到视频流,接下来就是将视频流回显到页面。这里使用video标签完成,代码如下:
<template><div class="video-page"><div class="video-content"><video ref="video" class="video-item"></video></div></div>
</template>export default {methods: {getUserMedia() {/* 可同时开启video(摄像头)和audio(麦克风) 这里只请求摄像头,所以只设置video为true */navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {/* 使用这个 stream 传递到成功回调中 */this.success(stream)}).catch(function(err) {/* 处理 error 信息 */this.error(error)});},success(stream) {console.log('成功', stream);/* 将stream 分配给video标签 */this.$refs.video.srcObject = stream;this.$refs.video.play();}}
}
这时,摄像头中的画面就可以显示在页面video标签内,如下图。
为了用户体验,在进入页面之前添加了判断摄像头是否已经接入并可用的逻辑,避免用户的摄像头未接入或者启动,造成应用不可用的错觉。
使用MediaDevices.enumerateDevices()
来获取可用媒体输入和输出设备的列表,例如摄像头、麦克风、耳机等。
navigator.mediaDevices.enumerateDevices().then(devicesList => {console.log('------devicesList', deviceList)
})
得到的设备列表数据格式如下:
kind
类型有三种,分别是audioinput
、audiooutput
和videoinput
。分别代表音视频的输入和输出。可在列表中查找目标媒体是否已经接入且可用。
若有选择切换设备需求,可根据kind
类型进行媒体设备分类,选择目标deviceId
,传入navigator.mediaDevices.getUserMedia
,完成来源切换。
navigator.mediaDevices.getUserMedia({ video: { deviceId: xxxx } })
拍照生成图片
拍照其实就是截取视频中的某一帧,这里使用canvas
来实现截取。getContext()
方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性。其中drawImage()
方法用来向画布上绘制图像、画布或视频。
<template><div class="video-page"><div class="video-content"><video ref="video" class="video-item" v-if="showVideo"></video><canvas ref="canvas" v-else width="500" height="346"></canvas><div class="video-buttons"><div @click="capture" class="button-item capture">拍照</div><div @click="submit" class="button-item submit"}">提交</div></div></div>
</template>export default {data: {showVideo: true, // 是否展示摄像头画面},methods: {/* 拍照按钮点击 */capture() {this.showVideo = falsevar context = this.$refs.canvas.getContext('2d');/* 要跟video的宽高一致 */context.drawImage(this.$refs.video, 0, 0, 1000, 692, 0, 0, 500, 346);}}
}
拍照的图片回显至canvas标签。
上传图片至CDN
上个步骤已经完成了拍照,接下来就需要将图片上传至CDN,拿到图片链接。这里有两种方式可以实现获取图片数据。
1. 使用HTMLCanvasElement.toBlob()
HTMLCanvasElement.toBlob()
方法生成 Blob
对象,用以展示 canvas 上的图片。因为直接可以拿到图片文件,所以无需再使用方法2中的函数来转化base64
,直接可以获取到图片文件用来上传。
语法
toBlob(callback, type, quality)
参数
callback
:回调函数,参数为Blob
对象(目标图片文件)。
type
:图片格式,默认为image/png
可选
。
quality
:0-1的数字,表示图片质量,可选
。
点击提交按钮按钮时,先获取图片文件,为上传做准备。
methods: {/* 提交按钮点击 */submit() {const base64Url = this.$refs.canvas.toBlob(blob => {console.log('===blob', blob)const data = new FormData()data.append('file', blob)request.post('https://XXXXX/upload', data)}, "image/jpeg", 0.95)}
}
console的结果如下图:
2. 使用HTMLCanvasElement.toDataURL()
HTMLCanvasElement.toDataURL()方法返回一个包含图片展示的Data URL。
Data URL
,即前缀为 data: 协议的 URL,其允许内容创建者向文档中嵌入小文件。
语法
canvas.toDataURL(type, encoderOptions);
参数
type
图片格式,默认为image/png
。
encoderOptions
0到1之间的值,用来选定图片质量,默认值是0.92,超出范围会使用默认值。
返回值
base64
组成的图片源数据,上传前需转为图片文件。这里封装了一个convertBase64UrlToImgFile
函数用来转换。代码如下:
<template><div class="video-page"><div class="video-content"><video ref="video" class="video-item" v-if="showVideo"></video><canvas ref="canvas" v-else width="500" height="346"></canvas><div class="video-buttons"><div @click="capture" class="button-item capture">拍照</div><div @click="submit" class="button-item submit">提交</div></div></div>
</template>export default {data: {/* 是否展示摄像头画面 */showVideo: true,},methods: {/* 将base64转为图片文件 */convertBase64UrlToImgFile(urlData, fileType) {const imgData = urlData.split('base64,').splice(-1)[0]/* 解码使用 base-64 编码的字符串 转换为byte */const bytes = window.atob(imgData)/* 处理异常,将ASCII码小于0的转换为大于0 */const ab = new ArrayBuffer(bytes.length)const ia = new Int8Array(ab)for (let i = 0; i < bytes.length; i++) {ia[i] = bytes.charCodeAt(i)}/* 转换成文件,可以添加文件的type,lastModifiedDate属性 */const blob = new Blob([ab], { type: fileType })blob.lastModifiedDate = new Date()return blob},/* 提交按钮点击 */async submit() {const base64Url = this.$refs.canvas.toDataURL()const imgFile = this.convertBase64UrlToImgFile(base64Url, 'image/jpg')console.log('====imgFile', imgFile)const data = new FormData()data.append('file', imgFile)/* 上传 */request.post('https://XXXXX/upload', data)},}
}
convertBase64UrlToImgFile
可用于在使用canvas
外的场景进行base64
转换图片文件。和HTMLCanvasElement.toBlob()
方法得到的结果一致。
以上两种方法都可以完成图片上传,最终拿到CDN图片链接后可传给后端进行处理。获取屏幕信息。
总结
通过以上四个步骤就完成了Electron应用中通过外接摄像头拍照并上传的功能。这里基本用不到Electron的能力,和在web端的实现方式并无区别,Electron在这里起到的作用就是获取摄像头媒体流不需要获取用户权限。
Electron
是基于Chromium
和Node.js
实现的,这就使前端开发者可以使用JavaScript
、HTML
和CSS
轻松构建跨平台的桌面应用。Electron
可以使用几乎所有的Web前端生态领域及Node.js
生态领域的组件和技术方案。
后续会介绍Electron在智能验机应用中的实践方案,敬请期待~
想了解更多转转公司的业务实践,点击关注下方的公众号吧!
Electron应用中实现调用外接摄像头并拍照上传相关推荐
- 在网页中调用摄像头实现拍照上传 - 高拍仪二次开发
在网页中调用摄像头实现拍照上传 高拍仪二次开发 在一些公共部门的办事处,比如银行.护照办理中心.税务等,我们可能会注意到办公桌上摆着这样一台机器.办公人员用它拍摄各种证件.文件.表格,有时候还 ...
- c++ 二次开发 良田高拍仪_在网页中调用摄像头实现拍照上传 - 高拍仪二次开发...
来源于 https://blog.csdn.net/weixin_40659738/article/details/78252562 在网页中调用摄像头实现拍照上传 高拍仪二次开发 在一些公共部门的 ...
- IE与非IE浏览器调用PC摄像头拍摄并且上传
需要下载源码以及相关文件的可以到(不好意思,之前上传的不知道怎么回事就没了) http://download.csdn.net/detail/u013946285/9886280 中下载 一,f ...
- chrome摄像头java_Chrome 谷歌浏览器调用摄像头并拍照上传 java示例
html页面: html5调用摄像头实现拍照 拍照 var video=document.getElementById("video"); var context=canvas.g ...
- pandorabox php,Openwrt Pandorabox 挂载摄像头 定时拍照上传百度网盘,实现实时监控(优酷路由宝)...
事情是这样的:三四年前为了实现一个200米左右的组网,到anywlan 恩山 Openwrt论坛等等学习了各种路由器固件,期间玩过基于Openwrt的wifi小车. 玩过一些路由器 DB120 网件 ...
- h5 调用ios原生相机拍照上传照片
1.html中的点击按钮和回调显示标签---------------直接上代码 <!DOCTYPE html> <html lang="en"> <h ...
- H5调用手机摄像头,实时拍照上传(旧)
H5调用手机摄像头,完成拍照,实时上传(旧) 项目开发中,偶尔会遇到网页中调用手机摄像头,通过相册选择或直接实时拍照的方式,完成图片上传的功能型需求. 今天,就通过一个小的案例,演示一下完整的实现流程 ...
- vue调用本地摄像头实现拍照
前言: vue调用本地摄像头实现拍照功能,由于调用摄像头有使用权限,只能在本地运行,线上需用https域名才可以使用. 实现效果: 1.摄像头效果: 2.拍照效果: 实现代码: <templat ...
- js调用pc摄像头实现拍照、录视频等,新版Chrome无访问http页面无法打开麦克风、摄像头
js调用pc摄像头实现拍照.录视频等,新版Chrome无访问http页面无法打开麦克风.摄像头 新版Chrome配置 vue环境下的前端 function部分 ##由于没有https环境,只有http ...
最新文章
- Scene Player初始版本完成
- bat自动输入密码登录_如何制作自动设置计算机管理员密码的脚本
- vux Cell组件
- Java HashSet的实现原理详解
- 为什么总是封板又打开涨停_警惕!如果股票涨停板反复打开说明了什么?
- 360智能工程中心期待你的加入
- Java笔记3:Eclipse添加jar包
- Dialog高仿Toast实现
- matlab无穷积分求解_matlab编程求无穷限定积分
- [GZOI2019GXOI2019]省选AFO记
- 加贺电子发表手掌大小的小型轻量DLP放映机
- c语言中的结构体定义和常见用法
- 手机上那些排版优雅的文章是怎么实现的?
- 关于小程序widthFix图片高度不能自适应的问题
- 如何在PPT中插入LaTeX公式
- 自然语言中corpora.Dictionary的理解
- 钜大锂电池并联串联知识详解 并联串联注意事项18650
- “资产证券化支持实体经济万里行”启幕 探索实体经济发展新态势
- 数智化重塑冷链物流行业,SaaS云系统开发方案赋能冷链企业实现高效运营
- php中获取金钱,PHP处理金钱和金钱价值观
热门文章
- sqlcommand连接并更新SQLServer数据库小实例
- 开始翻译Fielding的博士论文
- 医院住院收费管理系统源码 HIS源码 医院系统源码
- 《Foundations of Cryptography》chapter 1 Introduction
- 山东科技大学OJ题库 1014-自动拨出电话的程序
- wacom android 文件传输,Wacom sign pro PDF
- 【Excel VBA】批量拆分工作表为独立文件批量复制文件内容到总文件的工作表
- 北京协和医学院823计算机原理,2017年北京协和医学院基础医学院823计算机原理考研导师圈点必考题汇编...
- 你相信贷款200万30年买房会让银行从你身上获益近500万吗?
- Linux终端运行fasterrcnn,运行tensorflow版的fasterRCNN遇到的问题总结