PC端调用摄像头录制视频——vue标准写法
客户端——录制视频之“行”在PC端调用摄像头录制视频,传给后端生成链接。实现步骤:上代码(代码及属性介绍):在PC端调用摄像头录制视频,传给后端生成链接。说说最近做的这个功能的需求,就是简单的在PC端调起摄像头功能(非笔记本使用usb接口的摄像头),录制一个实时的视频,将录制的这个视频传递给后端生成一个链接展示。网上搜索了很多也没搜到满意的答案。最终只能自己来总结一下这个踩过了的坑。。。实现步骤:
·
客户端——录制视频之“行”
在PC端调用摄像头录制视频,传给后端生成链接。
说说最近做的这个功能的需求,就是简单的在PC端调起摄像头功能(非笔记本使用usb接口的摄像头),录制一个实时的视频,将录制的这个视频传递给后端生成一个链接展示。网上搜索了很多也没搜到满意的答案。最终只能自己来总结一下这个踩过了的坑。。。
实现步骤:
1.客户端的浏览器需要设置允许摄像头和麦克风的权限
2.使用原生js里面navigato中的mediaDevices属性去获取到视频流。
3.将获取的视频流转为file,再将file使用formData的方式传递给后端。
上代码(代码及属性介绍):
1、这是使用navigato、mediaDevices、getUserMedia的这几个属性判断浏览器是否开启摄像头、麦克风等,这一段代码网上有很多,就是对以上三个属性兼容性的方法封装。
属性介绍(MDN官方介绍):
navigato: navigato接口表示用户代理的状态和标识。 它允许脚本查询它和注册自己进行一些活动。
mediaDevices: mediaDevices是navigator 只读属性,返回一个mediaDevices对象,该对象可提供对相机和麦克风等媒体输入设备的连接访问,也包括屏幕共享。
getUserMedia: mediaDevices.getUserMedia()会提示用户给予使用媒体输入的许可,媒体输入会产生一个mediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
getCompetence() {
// 确保在页面渲染完毕后获取DOM
this.$nextTick(() => {
this.open = false; //切换成关闭摄像头
//我这是使用原生获取元素,可以使用vue的this.$refs.xxx
this.thisCancas = document.getElementById("canvasCamera");
this.thisContext = this.thisCancas.getContext("2d");
this.thisVideo = document.getElementById("videoCamera");
this.thisVideoData = document.getElementById("videoCameraData");//录像时的video
// 旧版本浏览器可能根本不支持mediaDevices,我们首先设置一个空对象
if (navigator.mediaDevices === undefined) {
navigator.mediaDevices = {};
}
// 部分浏览器实现了mediaDevices,使用getUserMedia进行覆盖现有属性,如果缺少getUserMedia属性,就进行添加
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = (constraints) => {
// 获取不同浏览器getUserMedia属性(兼容写法)
let getUserMedia =
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;
// 浏览器不支持,返回错误信息
if (!getUserMedia) {
//不支持getUserMedia时,同意返回错误信息
return Promise.reject(
new Error("此浏览器中未实现getUserMedia,不能调用摄像头")
);
}
// 支持getUserMedia时,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise((resolve, reject) => {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
if (navigator.mediaDevices.getUserMedia === undefined) {
navigator.mediaDevices.getUserMedia = (constraints) => {
// 首先获取现存的getUserMedia(如果存在)
let getUserMedia =
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.getUserMedia;
// 有些浏览器不支持,会返回错误信息
// 保持接口一致
if (!getUserMedia) {
return Promise.reject(
new Error("getUserMedia is not implemented in this browser")
);
}
// 否则,使用Promise将调用包装到旧的navigator.getUserMedia
return new Promise((resolve, reject) => {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
const constraints = {
//定义constraints:video和audio需要开启
audio: true,
video: {
width: this.videoWidth,
height: this.videoHeight,
transform: "scaleX(-1)",
},
};
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
// 旧的浏览器可能没有srcObject
if ("srcObject" in this.thisVideo) {
this.thisVideo.srcObject = stream;
} else {
// 避免在新的浏览器中使用它,新浏览器正在被弃用。没有开启摄像头权限或浏览器版本不兼容
this.thisVideo.src = window.URL.createObjectURL(stream);
}
this.thisVideo.onloadedmetadata = (e) => {
this.thisVideo.play();
};
// 录制视频窗口(这个窗口是录制视频时显示的窗口)
this.$refs.videoCameraData.srcObject = stream;
this.$refs.videoCameraData.play();
this.startRecording(stream);//调用录制控件方法,触发开始录制
})
.catch((err) => {
// 没有摄像头弹窗
this.isHave = false;
this.$alert(
"请在有摄像头的电脑上允许浏览器中的隐私设置使用摄像头,建议使用IE10以上及最新版谷歌、QQ、火狐等游浏览器观看网络课程。",
);
});
});
},
以上这段代码可以百度搜索到,这是获取到摄像头权限的原生方法。
2、就是控制录制视频开始和结束方法的操作,在正常获取到了摄像头和麦克风权限时触发。
属性介绍:
**mediaRecorde**r:MediaRecorder()构造函数会创建一个mediaStream进行录制的MediaRecorder对象。mediaRecorder可以很好的捕获到媒体流。
**mediaRecorder**的参数:
stream:mediaStream将要录制的媒体流,它可以来自于使用navigato.mediaDevices.getUserMedia()创建的流(如:视频流获取音频流等媒体流)。
**mediaRecorder**的方法:
start:开始将媒体流记录到一个或多个Buffer,得到的这个Buffer就是所捕获到的媒体流.
dataavailable:出发了开始录制,当数据有效时会触发这个方法,将数据存储在缓冲区,可以传event和data,此刻的data为真实的数据,也就是最终所捕获到的媒体流数据。
stop:停止录制,会触发最终Blob数据的dataavailable方法。
startRecording(stream) {
// console.log(stream,"stream");
// this.logger();
this.mediaRecorderData = new MediaRecorder(stream);
this.mediaRecorderData.start();
this.mediaRecorderData.addEventListener("dataavailable", (e)=> {
if (e.data.size > 0) {
this.videoCecorded.push(e.data);//视频录制视频流数据
};
});
this.mediaRecorderData.addEventListener("stop", ()=>{
// console.log("暂停 自动下载");
if(this.videoStatus != 1){
this.updataVideo();//上传实时录制的视频
}
});
this.mediaRecorderData.addEventListener("start", (e) => {
// console.log("开始 录制");
});
3.获取到数据与后台进行交互。
字段介绍:
videoCecorded:这是一个数组,将dataavailable方法中获取到的真实数据流获取到。然后将这个数据转为file,再将这个file使用formData的形式传给后端(我这最终后端会返回一个线上的视频链接)。
// 结束录制视频,触发基数录制视频事件
stopLive() {
// console.log(this.mediaRecorderData,"this.mediaRecorderData");
if (this.mediaRecorderData) {
this.mediaRecorderData.stop();
}
},
// 上传录制视频方法,获取视频地址
updata(){
var file = new File(this.videoCecorded, 'video-' + (new Date).toISOString().replace(/:|\./g, '-') + '.mp4', {
type: 'video/mp4'
});
let data = new FormData();
data.append('file', file);
return uploadVideoFile(data).then(res=>{
return this.recordVideoUrl = res.url;//获取上传的视频地址
})
}
写在最后,这是本人自己踩过的坑,已经成功解决,期间也花费了一些事件,不过最终还是跨过去了,在此与大家共勉,如果对你有帮助,请使用,如有疑问可以留眼,会及时回复提供力所能及的帮助。
更多推荐
已为社区贡献1条内容
所有评论(0)