Select Android 设备上的后置摄像头 - jsartoolkit5

Select rear camera on Android device - jsartoolkit5

我正在使用 jsartoolkit5 构建一个类似于 this example 的项目,我希望能够 select 我设备的后置摄像头而不是让 ChromeAndroid select 默认为前面一个。

根据此demo中的示例,我添加了以下代码以在设备有后置摄像头时自动切换摄像头。

var videoElement = document.querySelector('canvas');
function successCallback(stream) {
  window.stream = stream; // make stream available to console
  videoElement.src = window.URL.createObjectURL(stream);
  videoElement.play();
}

function errorCallback(error) {
  console.log('navigator.getUserMedia error: ', error);
}

navigator.mediaDevices.enumerateDevices().then(
  function(devices) {
    for (var i = 0; i < devices.length; i++) {
      if (devices[i].kind == 'videoinput' && devices[i].label.indexOf('back') !== -1) {
        if (window.stream) {
          videoElement.src = null;
          window.stream.stop();
        }
        var constraints = {
          video: {
            optional: [{
              sourceId: devices[i].deviceId
            }]
          }
        };
        navigator.getUserMedia(constraints, successCallback, errorCallback);
      }
    }
  }
); 

问题是它对 <video> 标签非常有效,但不幸的是 jsartoolkit 渲染了 canvas 中的内容,因此它会抛出错误。 我也尝试按照 Github 存储库中 this 已关闭问题中的说明进行操作,但这次我收到以下错误:DOMException: play() can only be initiated by a user gesture.

您知道如何解决这个问题或有什么建议吗?

提前感谢您的回复!

主要问题:

您正在混合新旧 getUserMedia 语法。
navigator.getUserMedia 已弃用,navigator.mediaDevices.getUserMedia 应该是首选。 另外,我认为 optional 不再是约束字典的一部分。

默认解决方案

这部分几乎是这个答案的重复:

你应该可以直接调用

navigator.mediaDevices.getUserMedia({
  video: {
    facingMode: {
      exact: 'environment'
      }
    }
  })

但是 chrome 仍然有 this bug, and even if @jib's answer states that it should work with adpater.js polyfill,我自己无法在我的 chrome 上为 Android 工作。

因此之前的语法目前仅适用于 Android.

的 Firefox

对于 chrome,您确实需要使用 enumerateDevices 以及 adapter.js 来使其工作,但是不要不要混淆语法,一切都应该没问题:

let handleStream = s => {
  document.body.append(
    Object.assign(document.createElement('video'), {
      autoplay: true,
      srcObject: s
    })
  );
}

navigator.mediaDevices.enumerateDevices().then(devices => {
  let sourceId = null;
  // enumerate all devices
  for (var device of devices) {
    // if there is still no video input, or if this is the rear camera
    if (device.kind == 'videoinput' &&
        (!sourceId || device.label.indexOf('back') !== -1)) {
      sourceId = device.deviceId;
    }
  }
  // we didn't find any video input
  if (!sourceId) {
    throw 'no video input';
  }
  let constraints = {
    video: {
      sourceId: sourceId
    }
  };
  navigator.mediaDevices.getUserMedia(constraints)
    .then(handleStream);
});
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

Fiddle for chrome 需要 https.

让它与 jsartoolkit 一起工作

您必须 fork jsartoolkit 项目并编辑 artoolkit.api.js

主项目目前禁用 mediaDevices.getUserMedia(),因此您需要再次启用它,并且您还必须添加对 sourceId 选项的检查,我们将添加稍后在 ARController.getUserMediaThreeScene() 通话中。

您可以在 this fork 中找到这些编辑的粗略和丑陋的实现。

所以一旦完成,您将不得不重建 js 文件,然后记得在您的代码中包含 adapter.js polyfill。

Here is a working fiddle 使用项目的演示之一。