浏览器调用摄像头getUserMedia
浏览器调用摄像头getUserMedia
2018年启动QQ浏览器会启动摄像头的新闻闹得沸沸扬扬。
前段时间公司让研究一下这个浏览器启用摄像头的功能,希望能够实现浏览器网页扫描二维码的功能。现在写下来记录一下。
浏览器启用摄像头是使用getUserMedia这个api实现的,调用后会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
有了这个api,使浏览器调用摄像头成为可能。但兼容性较差
自己测试华为自带浏览器,以及安卓微信浏览器测试通过。图上说支持的UC在12.0.8.988版本测试过发现支持这个getUserMedia方法,也成功回调了却不能成像,而小米自带浏览器测试发现不能打开摄像,应该是小米自带浏览器有安全性检测,浏览器不允许调用摄像头。
废话不多说,上代码:
html
<select id="select"></select>
<input type="button" title="开启摄像头" value="开启摄像头" "getMedia();" />
<div>
<video id="video" style="background:#000;" width="400" height="400"></video>
<canvas id='canvas' style="display: none;" width='400' height='400'></canvas>
</div>
js
var video = document.getElementById('video'), //摄像头
canvas = document.getElementById('canvas'), //截取图像
select = document.getElementById("select"), //切换摄像头
exArray = []; //存储设备源ID
//获取设备源ID navigator.getUserMedia需要
if (typeof MediaStreamTrack != 'undefined' && typeof MediaStreamTrack.getSources != 'undefined') {
MediaStreamTrack.getSources(function (sourceInfos) {
for (var i = 0; i != sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
//这里会遍历audio,video,所以要加以区分
if (sourceInfo.kind === 'video') {
exArray.push(sourceInfo.id);
}
}
});
}
function getMedia() {
if(window.stream) {
window.stream.getTracks().forEach(function(track) {
track.stop();
});
}
if (typeof navigator.mediaDevices == 'undefined' && typeof navigator.mediaDevices.getUserMedia == 'undefined') {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
if (typeof navigator.getUserMedia == 'undefined') {
return errorFunc({name: "ERROR", message: "navigator.getUserMedia is undefined!"});
}
for(var i = 0; i < exArray.length; i++) {
var option = document.createElement('option');
option.text = 'camera ' + (i + 1);
option.value = exArray[i];
select.appendChild(option);
}
var val = select.value;
navigator.getUserMedia({
'video': {
'optional': [{
'sourceId': val ? val : exArray[0]//0为前置摄像头,1为后置
}]
},
// 'video': true,
'audio': false
}, successFunc, errorFunc)
}
else {
navigator.mediaDevices.enumerateDevices().then(getDevice).catch(errorFunc);
var val = select.value;
var constraints = {
audio: false,
video: {deviceId: val ? {exact: val} : undefined}
// video: {facingMode: {exact : 'environment'}} //不起效
// video: true
}
navigator.mediaDevices.getUserMedia(constraints)
.then(function (stream) {
successFunc(stream);
return navigator.mediaDevices.enumerateDevices();
}).then(getDevice)
.catch(function (err) {
errorFunc(err);
});
}
}
function getDevice(deviceInfos) {
var val = select.value;
while(select.firstChild) {
select.removeChild(select.firstChild);
}
for(var i = 0; i !== deviceInfos.length; ++i) {
var deviceInfo = deviceInfos[i];
var option = document.createElement('option');
option.value = deviceInfo.deviceId;
if (deviceInfo.kind === 'videoinput') {
option.text = deviceInfo.label || 'camera ' + (select.length + 1);
select.appendChild(option);
}
}
if(select.value && select.value !== "") {
select.value = val;
}
}
//开启摄像头成功回调
function successFunc(stream) {
window.stream = stream;
if ("srcObject" in video) {
video.srcObject = stream;
} else if (video.mozSrcObject !== undefined) {
//Firefox中,video.mozSrcObject最初为null,而不是未定义的,我们可以靠这个来检测Firefox的支持
video.mozSrcObject = stream;
} else {
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
video.src = window.URL && window.URL.createObjectURL(stream) || stream;
}
video.onloadedmetadata = function (e) {
video.play();
};
}
//开启摄像头错误回调
function errorFunc(e) {
alert(e.name + ": " + e.message);
}
//截取图像
function screenShot() {
canvas.getContext('2d').drawImage(video, 0, 0, 400, 400);
var imgData = canvas.toDataURL("image/png", 0.8);
}
这是通过使用getUserMedia调用摄像后成像在canvas里,然后用canvas成图来扫描识别图片。
总结
以上代码有做兼容处理,能成像但不能放大,且不能聚焦,浏览器的支持率不高