计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能

系列文章总结 【前端vue——系列1】vue的路由
【前端vue——系列2】vue中的data是函数而不是对象与computed的实现原理
【前端vue——系列3】vue框架的优缺点;vue实现双向绑定
【前端vue——系列4】vuex和angular
【前端vue——系列5】生命周期详讲(vue的生命周期、页面的生命周期)
【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能

文章目录

  • 系列文章总结
  • 前言
  • 一、vue用到的api介绍
  • 二、vue实现各部分功能
    • 2.1 vue进行参数配置
    • 2.2 vue调用摄像头
    • 2.3 vue关闭摄像头
    • 2.4 截图拍照功能
    • 2.5 vue中展示本地图片的三种方式
      • 2.5.1 直接引入法
      • 2.5.2 在data中使用require
      • 2.5.3 在data里使用import导入
    • 2.6 将图片下载至本地功能
    • 2.7 摄像头开始工作后开始计时,暂停时停止计时
    • 2.8 将base64转换为file格式
    • 2.9 使用vue能够控制摄像头转动等
  • 三、功能截图展示
    • 3.1 打开摄像头
    • 3.2 暂停摄像头
    • 3.3 截图并且保存到本地

前言 前不久做了一个qt的展示摄象头拍摄的视频的,然后管理系统是用vue做的,最后集成的话可能会有些麻烦,所以我就想能不能用vue实现摄像头的视频展示等功能,下面为我测试成功了的示例:
提示:以下是本篇文章正文内容,下面案例可供参考
一、vue用到的api介绍
  • 本系统主要采用的是getUserMedia API为用户提供访问硬件设备媒体(摄像头、视频、音频、地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件下访问硬件媒体设备。
  • getUserMedia API最初是navigator.getUserMedia,目前已被最新Web标准废除,变更为navigator.mediaDevices.getUserMedia()
二、vue实现各部分功能 2.1 vue进行参数配置
【计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能】系统通过控制thisvideo的状态控制摄像头的(暂停、开始播放、结束)等操作,flag参数是在后续的过程中实现点击暂停,再点击又开始播放的判断标志位。
data () { return { videoWidth: 500, videoHeight: 300, number:0, hours: 0, minutes: 0, seconds: 0, run:false, imgSrc: '', flag:true, thisCancas: null, thisContext: null, thisVideo: null, userInfo: { imgStr:"" }, videoState: true } },

2.2 vue调用摄像头
  1. 首先获取现存的getUserMedia,并且保持接口一致
  2. 然后再使用navigator.mediaDevices.enumerateDevices()获取本地音频视频输入输出设备,找到要使用的设备id(这个设备id即为要展示的摄像头的标识id)
  3. 然后再通过获取到的设备deviceId填入video的deviceId中,就可以选择要调用的摄像头了
  4. 再通过两个if语句实现按钮的暂停播放切换
getCompetence () { this.videoState = false var _this = this this.thisCancas = document.getElementById('canvasCamera') this.thisContext = this.thisCancas.getContext('2d') this.thisVideo = document.getElementById('videoCamera')// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象 if (navigator.mediaDevices === undefined) { navigator.mediaDevices = {} } // 一些浏览器实现了部分mediaDevices,我们不能只分配一个对象 // 使用getUserMedia,因为它会覆盖现有的属性。 // 这里,如果缺少getUserMedia属性,就添加它。 if (navigator.mediaDevices.getUserMedia === undefined) { navigator.mediaDevices.getUserMedia = function (constraints) { // 首先获取现存的getUserMedia(如果存在) var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia // 有些浏览器不支持,会返回错误信息 // 保持接口一致 console.log('viedo',getUserMedia); if (!getUserMedia) { return Promise.reject(new Error('getUserMedia is not implemented in this browser')) } // 否则,使用Promise将调用包装到旧的navigator.getUserMedia return new Promise(function (resolve, reject) { getUserMedia.call(navigator, constraints, resolve, reject) }) } } //使用此方式获取本地音频视频输入输出设备,找到要使用的设备id,方式见下图 var enumeratorPromise = navigator.mediaDevices.enumerateDevices() console.log(enumeratorPromise) //把上面获取到的设备deviceId填入下面video的deviceId中,就可以选择要调用的摄像头了 var constraints = { audio: false, video: { deviceId: 'becf7e45fe56e42bcb4ec3f78b1b6b0fcffd6c6ccd890d30fffc2430a92c99bb', width: this.videoWidth, height: this.videoHeight } } navigator.mediaDevices.getUserMedia(constraints).then(function (stream) { // 旧的浏览器可能没有srcObject if ('srcObject' in _this.thisVideo) { _this.thisVideo.srcObject = stream } else { // 避免在新的浏览器中使用它,因为它正在被弃用。 _this.thisVideo.src = https://www.it610.com/article/window.URL.createObjectURL(stream) } _this.thisVideo.onloadedmetadata = function (e) {if (_this.flag==true){ _this.thisVideo.play(); _this.flag=false; } else { _this.thisVideo.pause() _this.flag=true; }} }).catch(err => { console.log(err) }) }

2.3 vue关闭摄像头 关闭摄像头就比较简单了,直接设置一个stop就可以实现
stopNavigator () { this.videoState = true this.thisVideo.srcObject.getTracks()[0].stop() }

2.4 截图拍照功能
  1. 该系统中是通过采用canvas绘图的方式,将采集到的数据帧进行绘图展示。
  2. 随后再将绘制的_this.imgSrc解码得到base64的格式的图片。
  3. clearImgSrc是再图片进行展示后再次绘图时将上一次的图片清除掉
setImage () { var _this = this _this.imgSrc=''; // 点击,canvas画图 _this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight) // 获取图片base64链接 _this.imgSrc = https://www.it610.com/article/this.thisCancas.toDataURL('image/png')//_this.imgSrc为解码得到的base64编码格式的图片 console.log('picture',_this.imgSrc) // this.$emit('setImgSrc', _this.imgSrc) console.log('转换',this.dataURLtoFile(_this.imgSrc, 'file')) }, clearImgSrc () { this.imgSrchttps://www.it610.com/article/= '' },

  1. 将图片以base64的格式展示出来如下所示:
{{imgSrc}}计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

2.5 vue中展示本地图片的三种方式 2.5.1 直接引入法
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

2.5.2 在data中使用require
> export default { data() { return { imgUrl:require('./image/1.jpg') } } }

2.5.3 在data里使用import导入
> import img from './image/1.jpg' export default { data() { return { imgUrl:img } } }

2.6 将图片下载至本地功能
  1. 必须同源才能下载。
  2. 需要在2.4中对图片进行截图后才能进行保存到本地操作,因为这里的href是取的this.imgSrc,即为展示的图片的索引
downs() { //必须同源才能下载 var alink = document.createElement("a"); alink.href = https://www.it610.com/article/this.imgSrc; alink.download =""; //图片名 alink.click(); },

2.7 摄像头开始工作后开始计时,暂停时停止计时
这其实就是一个很容易的计时器的功能,只需要将计时器的启动函数放入摄像头的启动事件中,将计时器的暂停函数放入摄像头的暂停事件中即可
methods: { num (n) { return n < 10 ? '0' + n : '' + n }, cutTimeDown () { var that = this var timer = window.setInterval(function () { if (that.run){ if (that.seconds === 59 ){ that.minutes += 1 that.seconds = 0 } if (that.minutes === 59 ) { that.hours += 1 that.minutes = 0 } // window.clearInterval(timer) else { that.seconds += 1 } } }, 1000) }, start(){ this.run=true; }, stop(){ this.run=false; }, }, watch: { second: { handler (newVal) { this.num(newVal) } }, minute: { handler (newVal) { this.num(newVal) } }, hour: { handler (newVal) { this.num(newVal) } } }, computed: { second: function () { return this.num(this.seconds) }, minute: function () { return this.num(this.minutes) }, hour: function () { return this.num(this.hours) } }, mounted () { this.cutTimeDown() }

2.8 将base64转换为file格式 不多说直接放代码:
base64转文件 dataURLtoFile (urlData, fileName) { let arr = urlData.split(','); let mime = arr[0].match(/:(.*?); /)[1]; let bytes = atob(arr[1]); // 解码base64 let n = bytes.length let ia = new Uint8Array(n); while (n--) { ia[n] = bytes.charCodeAt(n); } console.log('转换成功'); return new File([ia], fileName, { type: mime }); },

2.9 使用vue能够控制摄像头转动等
前面几个功能完成后本以为就已经万事大吉,没想到这个时候导师又来了一个需求,就是需要在能够看到视频的同时能够控制摄像头转动。
这个功能是在使用了萤石云的api的情况下实现摄像头的转动。
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

directionControl(num) { this.$http({ url:'https://open.ys7.com/api/lapp/token/get', method: 'post', params: {appKey: 'c11a991793ef6eebe7279fea9c98a55718fdbc88227a65736f3af85de40e7708', appSecret:'c11a991793ef6eebe7279fea9c98a55718fdbc88227a65736f3af85de40e7708'}, //传入摄像头的appkey和appsecrect timeout:2000 }).then(res=>{ // this.accessToken = res.accessToken; console.log('666',res); this.$http({ url:'https://open.ys7.com/api/lapp/device/ptz/start', method: 'post', params: { accessToken: this.accessToken, //accesstoken码,一般一周过期 speed:2, //旋转速度 direction:num, //方向,传入数字,对应数字在api文档有 channelNo:1, // 通道号 deviceSerial:'12132123' //序列号 }, timeout: 2000 }).then(res=>{ // console.log(res.data) if(res.data.code == '60000' ){ this.$message(res.data.msg) } }) }) }, stopTurn(){ this.$http({ url:'https://open.ys7.com/api/lapp/device/ptz/stop', method: 'post', params: { accessToken: this.accessToken, // direction:num, channelNo:1, // 通道号 deviceSerial:'c11a991793ef6eebe7279fea9c98a55718fdbc88227a65736f3af85de40e7708'//序列号 }, timeout: 2000 }).then(res=> { console.log('5555555',res.data); if(res.data.code == '60000' ){ this.$message(res.data.msg) } }) },

最后得出的大致操作展示如这样:
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

这里另外下了个插件axios的,过程如下:
cnpm install vue-axios --save

然后再到main.js中:
import axios from 'axios' Vue.prototype.$http = axios

三、功能截图展示 3.1 打开摄像头
忽略我的手指头,点击打开摄像头,既可以调用笔记本自带摄像头进行取景拍摄。
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

同时计时也会开始启动
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

3.2 暂停摄像头
在暂停摄像头的同时,计时也会开始暂停
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

同时计时也会开始暂停
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

3.3 截图并且保存到本地
  1. 点击拍照识别后,截图会保存到下面的展示中。
  2. 然后再点击下载即可以完成图片到本地的保存。
计算机网络|【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章图片

码字不易~, 各位看官要是看爽了,可不可以三连走一波,点赞皆有好运!,不点赞也有哈哈哈~~~

    推荐阅读