应如何格式化(Android)/ Chrome getUserMedia()约束?

时间:2016-01-09 17:18:19

标签: android html5 google-chrome html5-video

我一直试图在运行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,其语法不起作用。

2 个答案:

答案 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