Javascript GetUserMedia - 面对模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32086122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
GetUserMedia - facingmode
提问by Mikhail
I am currently using an Android tablet and GetUserMedia to take pictures in my program.
我目前正在使用 Android 平板电脑和 GetUserMedia 在我的程序中拍照。
Apparently, the default camera used by GetUserMedia is the front camera. How do I use the rear camera as a default?
显然,GetUserMedia 使用的默认摄像头是前置摄像头。如何默认使用后置摄像头?
Here's my code for GetUserMedia:
这是我的 GetUserMedia 代码:
navigator.getUserMedia({
"audio": false,
"video": {
mandatory: {
minWidth: this.params.dest_width,
minHeight: this.params.dest_height,
//facingMode: "environment",
},
}
},
function(stream) {
// got access, attach stream to video
video.src = window.URL.createObjectURL( stream ) || stream;
Webcam.stream = stream;
Webcam.loaded = true;
Webcam.live = true;
Webcam.dispatch('load');
Webcam.dispatch('live');
Webcam.flip();
},
function(err) {
return self.dispatch('error', "Could not access webcam.");
});
I inserted facingMode in the "mandatory" part but didn't work.
我在“强制”部分插入了 facesMode 但没有奏效。
Please help.
请帮忙。
回答by jib
Update:facingMode
is now available in Chrome for Android through the adapter.jspolyfill!
更新:facingMode
现在可通过adapter.js polyfill在Android 版Chrome 中使用!
facingMode
is not yet implemented in Chrome for Android, but works natively in Firefox for Android.
facingMode
是不是在Chrome尚未实施的Android,但在Firefox原生支持的Android。
You must use standardconstraints however: (use https fiddlefor Chrome):
但是,您必须使用标准约束:(Chrome使用https fiddle):
var gum = mode =>
navigator.mediaDevices.getUserMedia({video: {facingMode: {exact: mode}}})
.then(stream => (video.srcObject = stream))
.catch(e => log(e));
var stop = () => video.srcObject && video.srcObject.getTracks().forEach(t => t.stop());
var log = msg => div.innerHTML += msg + "<br>";
<button onclick="stop();gum('user')">Front</button>
<button onclick="stop();gum('environment')">Back</button>
<div id="div"></div><br>
<video id="video" height="320" autoplay></video>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
The { exact: }
syntax means the constraint is required, and things fail if the user doesn't have the right camera. If you leave it out then the constraint is optional, which in Firefox for Android means it only changes the default in the camera chooser in the permission prompt.
该{ exact: }
语法意味着需要进行约束,如果用户没有正确的相机事情失败。如果您省略它,则约束是可选的,这在 Firefox for Android 中意味着它只会更改权限提示中相机选择器中的默认值。
回答by Miojo_Esperto
Using Peter's code (https://stackoverflow.com/a/41618462/7723861) I came up with this solution to get the rear camera:
使用彼得的代码(https://stackoverflow.com/a/41618462/7723861)我想出了这个解决方案来获取后置摄像头:
function handleSuccess(stream) {
window.stream = stream; // make stream available to browser console
video.srcObject = stream;
}
function handleError(error) {
console.log('navigator.getUserMedia error: ', error);
}
var DEVICES = [];
var final = null;
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
var arrayLength = devices.length;
for (var i = 0; i < arrayLength; i++)
{
var tempDevice = devices[i];
//FOR EACH DEVICE, PUSH TO DEVICES LIST THOSE OF KIND VIDEOINPUT (cameras)
//AND IF THE CAMERA HAS THE RIGHT FACEMODE ASSING IT TO "final"
if (tempDevice.kind == "videoinput")
{
DEVICES.push(tempDevice);
if(tempDevice.facingMode == "environment" ||tempDevice.label.indexOf("facing back")>=0 )
{final = tempDevice;}
}
}
var totalCameras = DEVICES.length;
//If couldnt find a suitable camera, pick the last one... you can change to what works for you
if(final == null)
{
//console.log("no suitable camera, getting the last one");
final = DEVICES[totalCameras-1];
};
//Set the constraints and call getUserMedia
var constraints = {
audio: false,
video: {
deviceId: {exact: final.deviceId}
}
};
navigator.mediaDevices.getUserMedia(constraints).
then(handleSuccess).catch(handleError);
})
.catch(function(err) {
console.log(err.name + ": " + err.message);
});
回答by Peter Unsworth
Deploying our web app to android through Cordova, I tried multiple solutions to access the rear camera. The solution that worked for me was:
通过 Cordova 将我们的 Web 应用程序部署到 android,我尝试了多种解决方案来访问后置摄像头。对我有用的解决方案是:
constraints = {
audio: false,
video: {
width: 400,
height: 300,
deviceId: deviceId ? {exact: deviceId} : undefined
}
};
Retrieving the deviceId through:
通过以下方式检索 deviceId:
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
// devices is an array of accessible audio and video inputs. deviceId is the property I used to switch cameras
})
.catch(function(err) {
console.log(err.name + ": " + error.message);
});
I chose not to use a Cordova plugin so that if we choose to move away from Cordova, there would not be such a hefty migration.
我选择不使用 Cordova 插件,这样如果我们选择离开 Cordova,就不会有如此大的迁移。
回答by Théodore Tremblot
A pretty dandy snippet you can use is:
您可以使用的一个漂亮的花花公子片段是:
var front = false;
document.getElementById('flip-button').onclick = function() { front =` !front; };
var constraints = { video: { facingMode: (front? "user" : "environment") } };
This should work for you hopefully.
这应该对你有用。
回答by Yifan Sun
In the newer version of Chrome (after v52) the adaper.js solutions seem not working. So I solve the problem by enumerating devices first. Here is my solution. I am not sure if there is a better way to flip the camera and show the video on the screen. But I have to stop the track first and get a new stream.
在较新版本的 Chrome(v52 之后)中,adaper.js 解决方案似乎不起作用。所以我首先通过枚举设备来解决问题。这是我的解决方案。我不确定是否有更好的方法来翻转相机并在屏幕上显示视频。但是我必须先停止轨道并获得新的流。
let Video = function() {
let cameras = [];
let currCameraIndex = 0;
let constraints = {
audio: true,
video: {
deviceId: { exact: "" }
}
};
let videoCanvas = $('video#gum');
this.initialize = function() {
return enumerateDevices()
.then(startVideo);
};
this.flipCamera = function() {
currCameraIndex += 1;
if (currCameraIndex >= cameras.length) {
currCameraIndex = 0;
}
if (window.stream) {
window.stream.getVideoTracks()[0].stop();
}
return startVideo();
};
function enumerateDevices() {
return navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
devices.forEach(function(device) {
console.log(device);
if (device.kind === "videoinput") {
cameras.push(device.deviceId);
}
});
console.log(cameras);
});
}
function startVideo() {
constraints.video.deviceId.exact = cameras[currCameraIndex];
return navigator.mediaDevices.getUserMedia(constraints)
.then(handleSuccess).catch(handleError);
}
function handleSuccess(stream) {
videoCanvas[0].srcObject = stream;
window.stream = stream;
}
function handleError(error) {
alert(error);
}
};
回答by Nischal Jakhar
This would work for rear camera :
这适用于后置摄像头:
navigator.mediaDevices.getUserMedia({
video: {facingMode: "environment",
height:{<heightValueHere>},
width : {<widthValueHere>}
}
})
.then(function(stream){
window.stream = stream;
video.srcObject = stream;
})
回答by Mato
On some devices facingMode.exact
does not work as expected so you have to enumerate media devices and search for videoinput
devices with label containing "facing back".
在某些设备facingMode.exact
上无法按预期工作,因此您必须枚举媒体设备并搜索videoinput
标签包含“面向后”的设备。
Here is the code:
这是代码:
const devices = await navigator.mediaDevices.enumerateDevices()
const environmentCamera = devices.find(
device => device.kind === "videoinput" && device.label.includes("facing back")
)
const constraints = {
video: {
width: {
max: 640,
},
height: {
max: 480,
},
},
}
if (environmentCamera) {
constraints.video.deviceId = environmentCamera.deviceId
} else {
constraints.facingMode = {
exact: "environment",
}
}
const mediaStream = await navigator.mediaDevices.getUserMedia(constraints)
const mediaStreamTrack = mediaStream.getVideoTracks()[0]
// ...