我一直试图在运行Chrome的LG G4 Android手机上使用后置摄像头。我可以从MediaStreamTrack.getSources()
过滤掉视频来源,但是当我尝试设置约束以更喜欢后置摄像头时,我收到错误TypeError: Failed to execute 'webkitGetUserMedia' on 'Navigator': Malformed constraints object.
下面我有代码I&#39 ; m用于过滤视频源:
if (navigator.getUserMedia) {
if (MediaStreamTrack.getSources) {
MediaStreamTrack.getSources(function(sourceInfos) {
var sources = [];
_.forEach(sourceInfos, function(info) {
if (info.kind === 'video') {
sources.push(info);
}
})
handleSources(sources);
})
}
}
然后我尝试在上面提到的handleSources
函数中选择一个来源:
function handleSources(sources) {
var constraints = {
video: {
facingMode: 'environment' // Yeah, this definitely doesn't work.
}
}
getMedia(constraints); // This calls getUserMedia with the selected contraints
}
我已经为约束对象尝试了大量不同的格式,但它们似乎都不起作用。我知道我能够遍历所有来源并从那里选择环境相机,但我很想知道实际的语法是如何工作的。谷歌搜索答案只会显示https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#Parameters,其语法不起作用。
答案 0 :(得分:4)
看起来好像早期/不同版本的Android浏览器实现了不同的相机发现API。我发现我可以访问的每部手机(模拟器和物理)似乎都尊重不同的选项。更糟糕的是,这似乎是一个各种文档存储库坚持忽略或删除以前实现的API的领域(即使我们仍然需要知道如何使用它们,如果我们能够在除了最新的手机之外的任何东西上实现它们)。
我发现的API的两个主要风格是当前记录的(您在上面引用的API)和a version of the WebRTC specification from October 2013中记录的API。这种风格具有明显不同的约束规范,包括强制和可选属性。以上对getMedia的调用在旧规范下看起来像这样:
var constraints = {
video: {
mandatory: {
facingMode: 'environment'
}
}
}
getMedia(constraints);
或者,您可以使用可选设置,这些设置作为数组提供,因此您可以有多个选项(按顺序评估这些选项):
var constraints = {
video: {
optional: [{
facingMode: 'environment'
}]
}
}
getMedia(constraints);
话虽如此,在找到有效的过滤器时,您的里程可能会有所不同。例如,上面的facingMode
过滤器在我的Android 5.0模拟器中不起作用(它不会引发错误,但它也不会呈现面向环境的相机);但是,使用设备ID确实有效(在映射到您的示例时看起来像这样):
var constraints = {
video: {
mandatory: {
sourceId: '<your source ID here>'
}
}
}
getMedia(constraints);
对于我已经完成一些测试的Android 5.0模拟设备,我可以使用MediaStreamTrack.getSources()
找到我想要的设备(它会返回每个摄像头的facing
属性)。注意&#34;推荐&#34;此仿真设备中不存在替换方法navigator.mediaDevices.enumerateDevices()
方法。
在使用不同的模拟设备和物理设备时,您会看到许多其他问题,在现实世界中实现这些API时,每个设备都存在很多问题。我强烈建议您使用多个物理设备的组合(如果您处于可以访问它们的工作环境中),BrowserStack(为了给您提供大量真实和模拟的设备进行测试),console.log ()和Vorlon.js(从所有这些模拟设备实时查看console.log()输出,以便您可以看到实际发生的事情。)
我目前正在解决这个问题 - 如果我发现有关需要支持的不同API风格的其他内容,我会在此处发布更新。
答案 1 :(得分:2)
如果您查看链接到的MDN页面的Browser Compatibility部分,您会看到:
Chrome使用过时的约束语法,但此处描述的语法可通过adapter.js polyfill获取。
您会很高兴知道adapter.js现在支持Chrome for Android的facingMode
约束(对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().map(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>
{ exact: }
语法表示需要约束,如果用户没有合适的摄像头,则会失败。如果你把它留下来,那么约束是可选的(尽管在这种情况下,Firefox for Android会允许用户在权限提示中覆盖相机选择器中的选项)。
adapter.js还支持navigator.mediaDevices.enumerateDevices()
,已取代MediaStreamTrack.getSources
。