【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
系列文章总结【前端vue——系列1】vue的路由【前端vue——系列2】vue中的data是函数而不是对象与computed的实现原理【前端vue——系列3】vue框架的优缺点;vue实现双向绑定【前端vue——系列4】vuex和angular【前端vue——系列5】生命周期详讲(vue的生命周期、页面的生命周期)文章目录系列文章总结前言一、vue用到的api介绍二、vue实现各部分功能2.1 v
系列文章总结
【前端vue——系列1】vue的路由
【前端vue——系列2】vue中的data是函数而不是对象与computed的实现原理
【前端vue——系列3】vue框架的优缺点;vue实现双向绑定
【前端vue——系列4】vuex和angular
【前端vue——系列5】生命周期详讲(vue的生命周期、页面的生命周期)
【前端vue——系列6】vue连接摄像头并实现摄像头暂停,计时,截图到本地等功能
文章目录
前言
前不久做了一个qt的展示摄象头拍摄的视频的,然后管理系统是用vue做的,最后集成的话可能会有些麻烦,所以我就想能不能用vue实现摄像头的视频展示等功能,下面为我测试成功了的示例:
提示:以下是本篇文章正文内容,下面案例可供参考
一、vue用到的api介绍
- 本系统主要采用的是
getUserMedia API
为用户提供访问硬件设备媒体(摄像头、视频、音频、地理位置等)的接口,基于该接口,开发者可以在不依赖任何浏览器插件的条件下访问硬件媒体设备。 getUserMedia API
最初是navigator.getUserMedia
,目前已被最新Web标准废除,变更为navigator.mediaDevices.getUserMedia()
二、vue实现各部分功能
2.1 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调用摄像头
- 首先获取现存的
getUserMedia
,并且保持接口一致 - 然后再使用
navigator.mediaDevices.enumerateDevices()
获取本地音频视频输入输出设备,找到要使用的设备id(这个设备id即为要展示的摄像头的标识id) - 然后再通过获取到的设备
deviceId
填入video的deviceId
中,就可以选择要调用的摄像头了 - 再通过两个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 = 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 截图拍照功能
- 该系统中是通过采用
canvas
绘图的方式,将采集到的数据帧进行绘图展示。 - 随后再将绘制的
_this.imgSrc
解码得到base64
的格式的图片。 clearImgSrc
是再图片进行展示后再次绘图时将上一次的图片清除掉
setImage () {
var _this = this
_this.imgSrc='';
// 点击,canvas画图
_this.thisContext.drawImage(_this.thisVideo, 0, 0, _this.videoWidth, _this.videoHeight)
// 获取图片base64链接
_this.imgSrc = 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.imgSrc = ''
},
- 将图片以base64的格式展示出来如下所示:
<div>
{{imgSrc}}
<img :src="'data:image/jpeg;base64' + imgSrc" alt="" class="img1">
</div>
2.5 vue中展示本地图片的三种方式
2.5.1 直接引入法
<img src="./image/1.jpg"/>
2.5.2 在data中使用require
<template>
<img :src="imgUrl">
</template>
<script>
export default {
data() {
return {
imgUrl:require('./image/1.jpg')
}
}
}
</script>
2.5.3 在data里使用import导入
<template>
<img :src="imgUrl">
</template>
<script>
import img from './image/1.jpg'
export default {
data() {
return {
imgUrl:img
}
}
}
</script>
2.6 将图片下载至本地功能
- 必须同源才能下载。
- 需要在2.4中对图片进行截图后才能进行保存到本地操作,因为这里的
href
是取的this.imgSrc
,即为展示的图片的索引
downs() {
//必须同源才能下载
var alink = document.createElement("a");
alink.href = 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的情况下实现摄像头的转动。
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)
}
})
},
最后得出的大致操作展示如这样:
这里另外下了个插件axios的,过程如下:
cnpm install vue-axios --save
然后再到main.js中:
import axios from 'axios'
Vue.prototype.$http = axios
三、功能截图展示
3.1 打开摄像头
忽略我的手指头,点击打开摄像头,既可以调用笔记本自带摄像头进行取景拍摄。
同时计时也会开始启动
3.2 暂停摄像头
在暂停摄像头的同时,计时也会开始暂停
同时计时也会开始暂停
3.3 截图并且保存到本地
- 点击拍照识别后,截图会保存到下面的展示中。
- 然后再点击下载即可以完成图片到本地的保存。
码字不易~, 各位看官要是看爽了,可不可以三连走一波,点赞皆有好运!,不点赞也有哈哈哈~~~
更多推荐
所有评论(0)