一、项目需求
通过H5打开本地摄像头,实时将视频转化为base64的字符串,传输到后台。
二、项目环境
使用vue cl3 创建项目,添加axios插件,使用axios与后台实现通信和交互。
三、知识点
1.navigator.mediaDevices.getUserMedia
mediaDevices.getUserMedia()会提示用户给予使用媒体输入的许可(提示我们是否允许当前页面打开摄像头),媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道、一个音频轨道,也可能是其他轨道类型。
MDN有关meidaDevices.getUserMedia描述
语法 :
var userMedia = navigator.mediaDevice.getUserMedia(constraints).then().catch();
webkit核心浏览器兼容:
var userMedia = navigator.webkitGetUserMedia(constraints,success, error);
firfox浏览器兼容:
var userMedia = navigator.mozGetUserMedia(contraints, success, error);
旧版兼容:
var userMedia = navigator.getUserMedia(contraints, success, error);
2.MediaRecorder
MediaRecorder()构造函数会创建一个对指定的MediaStream进行录制的MediaRecorder对象
MDN有关MediaRecorder描述
语法:
var mediaRecorder = new MediaRecorder(stream[, options]);
这里着重要看的ondataavailable,onstart,onstop这三个钩子函数和start, stop这两个函数,后期控制MediaRecorder开启和关闭会用到。
3.canvas的有关知识
主要知识点是drawImage()将视频实时显示到canvas上,toDataUrl()将cavas转化为base64字符串(实现将视频信息转化位base64)
四、基础代码展示
<template>
<div class="pages">
<video ref="video" width="480" height="320" style="display:none"></video>
<canvas ref="canvas" width="480" height="320"></canvas>
</div>
</template>
<script>
export default {
data() {
return {
video: '',
mediaRecorder: '',
img: '',
canvas: '',
context: '',
}
},
methods: {
//访问用户媒体设备的兼容方法
getUserMedia(constraints, success, error) {
if (navigator.mediaDevices.getUserMedia) {
//最新的标准API
navigator.mediaDevices.getUserMedia(constraints).then(success)
.catch(error);
} else if (navigator.webkitGetUserMedia) {
//webkit核心浏览器
navigator.webkitGetUserMedia(constraints,success, error)
} else if (navigator.mozGetUserMedia) {
//firfox浏览器
navigator.mozGetUserMedia(constraints, success, error);
} else if (navigator.getUserMedia) {
//旧版API
navigator.getUserMedia(constraints, success, error);
}
},
success(stream) {
var self = this;
this.mediaRecorder = new MediaRecorder(stream);
if(this.mediaRecorder.state != "recording") {
this.mediaRecorder.start(10);
}
//将视频流设置为video元素的源
this.video.srcObject = stream;
this.video.play();
this.mediaRecorder.ondataavailable = function() {
self.context.drawImage(self.video, 0, 0, 480, 320);
self.img = self.canvas.toDataURL('image/png');
}
this.mediaRecorder.onstart = function() {
self.context.drawImage(self.video, 0, 0, 480, 320);
self.img = self.canvas.toDataURL('image/png');
};
},
error(error) {
console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
},
stopRecorder(){
this.timer.stop();
if(this.mediaRecorder.state == "recording") {
this.mediaRecorder.stop();
}else {
console.log(this.mediaRecorder.state);
}
},
},
mounted() {
this.video = this.$refs['video'];
this.canvas = this.$refs['canvas'];
this.context = this.canvas.getContext('2d');
if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
//调用用户媒体设备, 访问摄像头
this.getUserMedia({video : {width: 480, height: 320}}, this.success,
this.error);
} else {
alert('不支持访问用户媒体');
}
},
destroyed() {
// 关闭记录
this.stopRecorder();
}
}
</script>
<style scoped>
</style>
五、注意事项
navigator.mediaDevices.getUserMedia()只能在localhost和https模式才能打开本地的摄像头。传输到后台的base64位要注意对+号进行处理后使用,因此需要使用encodeURIComponent()函数进行二次编码。