(Android) / Chrome getUserMedia() 约束应该如何格式化?
Posted
技术标签:
【中文标题】(Android) / Chrome getUserMedia() 约束应该如何格式化?【英文标题】:How should (Android) / Chrome getUserMedia() constraints be formatted? 【发布时间】:2016-04-14 06:51:15 【问题描述】:我一直在尝试访问运行 Chrome 的 LG G4 android 手机上的后置摄像头。我能够从MediaStreamTrack.getSources()
中过滤掉视频源,但是当我尝试设置一个约束以偏爱后置摄像头时,我收到错误TypeError: Failed to execute 'webkitGetUserMedia' on 'Navigator': Malformed constraints object.
下面我有用于过滤视频源的代码:
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,其语法不起作用。
【问题讨论】:
【参考方案1】:似乎较早/不同版本的 Android 浏览器实现了不同的 API 用于相机发现。我发现我可以访问的每部手机(模拟器和物理)似乎都尊重一组不同的选项。更糟糕的是,这似乎是各种文档存储库坚持忽略或删除先前实现的 API 的领域(即使我们仍然需要知道如何使用它们,如果我们要能够在除最新手机之外的任何东西上实现的话)。
我发现的 API 的两种主要风格是当前记录的一种(您参考上面的 API)和a version of the WebRTC specification from October 2013 中记录的一种。这种风格具有显着不同的约束规范,包括强制和可选属性。在旧规范下,您对 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
属性)。请注意,此模拟设备中不存在“推荐”替换方法navigator.mediaDevices.enumerateDevices()
。
在使用不同的模拟设备和物理设备时,您会看到许多其他问题,在现实世界中实现这些 API 时,每个问题都给我带来了很大的问题。我强烈建议使用多个物理设备的组合(如果您在可以访问它们的工作环境中),BrowserStack(为您提供大量真实和模拟设备进行测试),console.log()和Vorlon.js(从所有这些模拟设备实时查看console.log() 输出,以便您了解实际情况)。
我目前正在解决这个确切的问题 - 如果我发现任何关于需要支持的不同 API 风格的其他信息,我将在此处发布更新。
【讨论】:
感谢您的深入回复!我已经实现了一个解决方案,用户可以在其中选择一个可用的来源,但这是一个额外的步骤,才能显示实际的相机流,因此不是最佳的。如果我再次在相机上工作,我一定会稍后在这里签到。【参考方案2】:如果您查看链接到的 MDN 页面的 Browser Compatibility 部分,您会看到:
Chrome 使用过时的约束语法,但此处描述的语法可通过 adapter.js polyfill 获得。
您会很高兴知道 adapter.js 现在支持 Android 版 Chrome 上的 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" autoplay></video>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
exact:
语法意味着约束是必需的,如果用户没有正确的相机,事情就会失败。如果您将其省略,则该约束是可选的(尽管在这种情况下,Firefox for Android 将允许用户在权限提示中覆盖相机选择器中的选择)。
adapter.js 还支持navigator.mediaDevices.enumerateDevices()
,它已经取代了MediaStreamTrack.getSources
。
【讨论】:
以上是关于(Android) / Chrome getUserMedia() 约束应该如何格式化?的主要内容,如果未能解决你的问题,请参考以下文章