MediaDevices.getUserMedia()的运用

判断函数有两个 switch 和 if 语句

MediaDevices.getUserMedia() 方法提示用户允许使用媒体输入,该媒体输入会生成一个 MediaStream,其中包含包含所请求的媒体类型的轨道。

例如,该流可以包括视频轨道(由硬件或虚拟视频源(如摄像机、视频录制设备、屏幕共享服务等)生成)、音轨(类似地,由物理或虚拟音频源(如麦克风、A/D 转换器等)生成)以及可能的其他轨道类型。

它返回解析为 MediaStream 对象的承诺。如果用户拒绝权限,或者匹配的媒体不可用,则承诺将分别与 DOMException 或 DOMException 一起被拒绝。NotAllowedErrorNotFoundError

注意:返回的承诺可能既不能解决也不能拒绝,因为用户根本不需要做出选择,并且可能会忽略请求。

通常,您将使用 navigator.mediaDevices 访问 MediaDevices 单例对象,如下所示:

<span style="color:#1b1b1b"><span style="background-color:#ffffff"><span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-tag)">async</span> <span style="color:var(--code-token-tag)">function</span> <span style="color:var(--code-token-attribute-name)">getMedia</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-tag)">let</span> stream = <span style="color:var(--code-token-tag)">null</span><span style="color:var(--code-token-punctuation)">;</span>

  <span style="color:var(--code-token-tag)">try</span> <span style="color:var(--code-token-punctuation)">{</span>
    stream = <span style="color:var(--code-token-tag)">await</span> navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
    <span style="color:var(--code-token-comment)">/* use the stream */</span>
  <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-tag)">catch</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
    <span style="color:var(--code-token-comment)">/* handle the error */</span>
  <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>
</code></span></span></span></span>

同样,直接使用原始承诺,代码如下所示:

<span style="color:#1b1b1b"><span style="background-color:#ffffff"><span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code>navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">then</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>stream<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-comment)">/* use the stream */</span>
<span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">catch</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-comment)">/* handle the error */</span>
<span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
</code></span></span></span></span>

注意:如果当前文档未安全加载,则 将为 ,并且您无法使用 。有关此问题以及与使用相关的其他安全问题的详细信息,请参阅安全性。navigator.mediaDevicesundefinedgetUserMedia()getUserMedia()

语法

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span>
</code></span></span>

参数

constraints

一个对象,用于指定要请求的媒体类型以及每种类型的任何要求。

该参数是具有两个成员的对象:和 ,描述请求的媒体类型。必须指定其中之一或两者。如果浏览器无法找到具有满足给定约束的指定类型的所有媒体轨道,则返回的承诺将被 DOMException 拒绝。constraintsvideoaudioNotFoundError

以下请求音频和视频,没有任何特定要求:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-attribute-value)">true</span> <span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

如果为媒体类型指定,则生成的流需要包含该类型的轨道。如果由于任何原因无法包含一个,则调用将导致错误。truegetUserMedia()

虽然由于隐私原因无法访问有关用户摄像头和麦克风的信息,但应用程序可以使用其他约束请求其需要和想要的摄像头和麦克风功能。以下表示对 1280x720 相机分辨率的偏好:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span>
  <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">width</span>: <span style="color:var(--code-token-attribute-value)">1280</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">height</span>: <span style="color:var(--code-token-attribute-value)">720</span> <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

浏览器将尝试遵守此要求,但如果完全匹配不可用,或者用户覆盖它,则可能会返回其他分辨率。

若要要求某项功能,请使用关键字 、 或 (又名 )。以下要求最低分辨率为 1280x720:minmaxexactmin == max

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span>
  <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span>
    <span style="color:var(--code-token-attribute-name)">width</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">min</span>: <span style="color:var(--code-token-attribute-value)">1280</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">,</span>
    <span style="color:var(--code-token-attribute-name)">height</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">min</span>: <span style="color:var(--code-token-attribute-value)">720</span> <span style="color:var(--code-token-punctuation)">}</span>
  <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

如果不存在具有此分辨率或更高分辨率的相机,则返回的承诺将被拒绝,并且不会提示用户。OverconstrainedError

行为差异的原因是关键字 , 和 本质上是强制性的。而普通值和调用的关键字则不是。下面是一个完整的示例:minmaxexactideal

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span>
  <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span>
    <span style="color:var(--code-token-attribute-name)">width</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">min</span>: <span style="color:var(--code-token-attribute-value)">1024</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">ideal</span>: <span style="color:var(--code-token-attribute-value)">1280</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">max</span>: <span style="color:var(--code-token-attribute-value)">1920</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">,</span>
    <span style="color:var(--code-token-attribute-name)">height</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">min</span>: <span style="color:var(--code-token-attribute-value)">576</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">ideal</span>: <span style="color:var(--code-token-attribute-value)">720</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">max</span>: <span style="color:var(--code-token-attribute-value)">1080</span> <span style="color:var(--code-token-punctuation)">}</span>
  <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

使用时,一个值具有重力,这意味着浏览器将尝试找到设置(和相机,如果您有多个),与给定的理想值的最小健身距离ideal

普通值本质上是理想的,这意味着我们上面的第一个分辨率示例可以这样编写:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span>
  <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span>
    <span style="color:var(--code-token-attribute-name)">width</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">ideal</span>: <span style="color:var(--code-token-attribute-value)">1280</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">,</span>
    <span style="color:var(--code-token-attribute-name)">height</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">ideal</span>: <span style="color:var(--code-token-attribute-value)">720</span> <span style="color:var(--code-token-punctuation)">}</span>
  <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

并非所有约束都是数字。例如,在移动设备上,以下设备将优先选择前置摄像头(如果有)而不是后置摄像头:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">facingMode</span>: <span style="color:var(--code-token-attribute-value)">"user"</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

要求使用后置摄像头,请使用:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">facingMode</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">exact</span>: <span style="color:var(--code-token-attribute-value)">"environment"</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

另一个非数字约束是约束。如果您有来自 mediaDevices.enumerateDevices()的,则可以使用它来请求特定设备:deviceIddeviceId

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">deviceId</span>: myPreferredCameraDeviceId <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

上述内容将返回您请求的相机,或者如果该特定相机不再可用,则返回其他相机。同样,要要求使用特定的相机,您可以使用:

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">deviceId</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">exact</span>: myExactCameraOrBustDeviceId <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span>
</code></span></span>

返回值

一个 Promise,其履行处理程序在成功获取请求的媒体时接收 MediaStream 对象。

异常

AbortError DOMException

尽管用户和操作系统都授予了对硬件设备的访问权限,并且没有发生会导致 DOMException 的硬件问题,但如果发生某些问题导致设备无法使用,请抛出。NotReadableError

NotAllowedError DOMException

如果此时无法使用一个或多个请求的源设备,则抛出。如果浏览上下文不安全(即,页面是使用 HTTP 而不是 HTTPS 加载的),则会发生这种情况。如果用户指定不允许当前浏览实例访问设备,用户拒绝访问当前会话,或者用户已拒绝全局访问用户媒体设备的所有访问,也会发生这种情况。在支持使用功能策略管理媒体权限的浏览器上,如果未将功能策略配置为允许访问输入源,则会返回此错误。

注意:用于此目的的规范的旧版本; 有了新的含义。SecurityErrorSecurityError

NotFoundError DOMException

如果未找到满足给定约束的指定类型的媒体轨道,则抛出。

NotReadableError DOMException

如果尽管用户授予了使用匹配设备的权限,但在操作系统、浏览器或网页级别发生硬件错误,从而阻止了对设备的访问,则抛出。

OverconstrainedError DOMException

如果指定的约束导致没有符合请求条件的候选设备,则抛出。error 是 一个类型为 的对象,并且具有一个属性,其字符串值是无法满足的约束的名称,并且具有包含解释该问题的人类可读字符串的属性。OverconstrainedErrorconstraintmessage

注意:由于即使用户尚未授予使用基础设备的权限,也可能发生此错误,因此它可能被用作指纹图面。

SecurityError DOMException

如果在调用的文档上禁用了用户媒体支持,则抛出。启用和禁用用户媒体支持的机制由各个用户代理决定。getUserMedia()

TypeError

如果指定的约束列表为空,或者所有约束都设置为 ,则抛出。如果您尝试在不安全的上下文中调用,也可能发生这种情况,因为navigator.mediaDevices处于不安全的上下文中。falsegetUserMedia()undefined

隐私和安全

作为一个可能涉及重大隐私问题的API,'的规范列出了浏览器有义务满足的各种隐私和安全要求。getUserMedia()

getUserMedia()是一个强大的功能,只能在安全的上下文中使用;在不安全的上下文中,是 ,阻止访问 。简而言之,安全上下文是使用 HTTPS 或 URL 方案加载的页面,或者是从 加载的页面。navigator.mediaDevicesundefinedgetUserMedia()file:///localhost

此外,始终需要用户权限才能访问用户的音频和视频输入。只有窗口的有效源的顶级文档上下文才能请求使用权限,除非顶级上下文明确授予给定<iframe>使用功能策略执行此操作的权限。否则,甚至永远不会要求用户获得使用输入设备的权限。getUserMedia()

有关这些要求和规则的其他详细信息、它们如何反映在代码运行的上下文中,以及有关浏览器如何管理用户隐私和安全问题的其他详细信息,请继续阅读。

用户隐私

作为可能涉及重大隐私问题的API,规范要求对用户通知和权限管理有非常具体的要求。首先,在打开任何媒体收集输入(如网络摄像头或麦克风)之前,必须始终获得用户权限。浏览器可能会提供每个域一次的权限功能,但它们必须至少在第一次询问,并且用户必须专门授予持续权限(如果他们选择这样做)。getUserMedia()getUserMedia()

同样重要的是通知规则。浏览器需要显示一个指示器,该指示器显示摄像头或麦克风正在使用中,高于可能存在的任何硬件指示器。它们还必须显示一个指示器,指示已授予使用设备进行输入的权限,即使该设备目前未主动录制也是如此。

例如,在 Firefox 中,URL 栏显示一个红色的脉冲图标,表示正在进行录制。如果权限已到位,但当前未进行录制,则该图标为灰色。设备的物理光用于指示录制当前是否处于活动状态。如果您已将相机静音(所谓的“面部静音”),则相机的活动指示灯会熄灭,以指示相机未主动录制您,而不会丢弃静音结束后继续使用相机的权限。

安全

用户代理中的安全管理和控制可以通过多种方式导致返回与安全相关的错误。getUserMedia()

注意:的安全模型仍然在一定程度上处于变化之中。最初设计的安全机制正在被功能策略取代,因此各种浏览器使用不同的机制具有不同级别的安全支持。您应该在各种设备和浏览器上仔细测试您的代码,以确保它尽可能广泛地兼容getUserMedia()

功能策略

HTTP的功能策略安全管理功能正在引入浏览器中,许多浏览器在一定程度上支持(尽管默认情况下并不总是启用,如Firefox)。 是一种需要使用功能策略的方法,您的代码需要准备好来处理这种情况。例如,您可能需要在使用 的任何<iframe>上使用 allow 属性,而使用 的页面最终将需要提供功能策略标头。getUserMedia()getUserMedia()getUserMedia()

应用于 的两个权限是 和 。getUserMedia()cameramicrophone

例如,HTTP 标头中的此行将允许对文档和从同一源加载的任何嵌入的<iframe>元素使用相机:

<span style="background-color:var(--code-background-block)">Feature-Policy: camera 'self'
</span>

这将请求访问当前源和特定源 https://developer.mozilla.org 麦克风:

<span style="background-color:var(--code-background-block)">Feature-Policy: microphone 'self' https://developer.mozilla.org
</span>

如果您在 中使用,则可以仅针对该框架请求权限,这显然比请求更通用的权限更安全。在这里,表明我们需要同时使用摄像头和麦克风的能力:getUserMedia()<iframe>

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-punctuation)"><</span>iframe</span> <span style="color:var(--code-token-attribute-name)">src</span><span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-punctuation)">=</span><span style="color:var(--code-token-punctuation)">"</span>https://mycode.example.net/etc<span style="color:var(--code-token-punctuation)">"</span></span> <span style="color:var(--code-token-attribute-name)">allow</span><span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-punctuation)">=</span><span style="color:var(--code-token-punctuation)">"</span>camera;microphone<span style="color:var(--code-token-punctuation)">"</span></span><span style="color:var(--code-token-punctuation)">></span></span>
<span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-attribute-value)"><span style="color:var(--code-token-punctuation)"></</span>iframe</span><span style="color:var(--code-token-punctuation)">></span></span>
</code></span></span>

阅读我们的指南“使用功能策略”,详细了解其工作原理。

基于加密的安全性

该方法仅在安全上下文中可用。安全上下文是指浏览器有理由相信包含使用 HTTPS/TLS 安全加载的文档,并且对不安全上下文的暴露程度有限。如果未在安全上下文中加载文档,则 navigator.mediaDevices 属性为 ,因此无法访问。getUserMedia()undefinedgetUserMedia()

在这种情况下尝试访问将导致类型错误getUserMedia()

文档源安全性

由于存在明显的安全问题,如果意外使用或未仔细管理安全性,则只能在安全环境中使用。加载文档有许多不安全的方法,这些方法反过来可能会尝试调用 。以下是不允许调用的情况示例:getUserMedia()getUserMedia()getUserMedia()

  • 加载到沙盒<iframe>元素的文档无法调用,除非其沙盒属性设置为 。getUserMedia()<iframe>allow-same-origin
  • 使用 没有来源的 或 URL 加载的文档(例如,当用户在地址栏中键入其中一个 URL 时)无法调用 。从 JavaScript 代码加载的这些类型的 URL 继承脚本的权限。data://blob://getUserMedia()
  • 没有源的任何其他情况,例如使用 srcdoc 属性指定帧的内容时。

例子

宽度和高度

此示例给出了摄像机分辨率的首选项,并将生成的 MediaStream 对象分配给视频元素。

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-comment)">// Prefer camera resolution nearest to 1280x720.</span>
<span style="color:var(--code-token-tag)">var</span> constraints = <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">width</span>: <span style="color:var(--code-token-attribute-value)">1280</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">height</span>: <span style="color:var(--code-token-attribute-value)">720</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>

navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">then</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>mediaStream<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-tag)">var</span> video = document<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">querySelector</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-attribute-value)">'video'</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  video<span style="color:var(--code-token-punctuation)">.</span>srcObject = mediaStream<span style="color:var(--code-token-punctuation)">;</span>
  video<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">onloadedmetadata</span> = <span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>e<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
    video<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">play</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>
<span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">catch</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span> console<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">log</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">.</span>name + <span style="color:var(--code-token-attribute-value)">": "</span> + err<span style="color:var(--code-token-punctuation)">.</span>message<span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span> <span style="color:var(--code-token-comment)">// always check for errors at the end.</span>
</code></span></span>

在较旧的浏览器中使用新的 API

下面是使用 和 polyfill 一起使用 的示例,以处理较旧的浏览器。请注意,此 polyfill 无法纠正约束语法中的旧式差异,这意味着约束在浏览器之间无法正常工作。建议改用适配器.js polyfill,这确实可以处理约束。navigator.mediaDevices.getUserMedia()

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-comment)">// Older browsers might not implement mediaDevices at all, so we set an empty object first</span>
<span style="color:var(--code-token-tag)">if</span> <span style="color:var(--code-token-punctuation)">(</span>navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices === <span style="color:var(--code-token-tag)">undefined</span><span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices = <span style="color:var(--code-token-punctuation)">{</span><span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>
<span style="color:var(--code-token-punctuation)">}</span>

<span style="color:var(--code-token-comment)">// Some browsers partially implement mediaDevices. We can't just assign an object</span>
<span style="color:var(--code-token-comment)">// with getUserMedia as it would overwrite existing properties.</span>
<span style="color:var(--code-token-comment)">// Here, we will just add the getUserMedia property if it's missing.</span>
<span style="color:var(--code-token-tag)">if</span> <span style="color:var(--code-token-punctuation)">(</span>navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span>getUserMedia === <span style="color:var(--code-token-tag)">undefined</span><span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getUserMedia</span> = <span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>constraints<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>

    <span style="color:var(--code-token-comment)">// First get ahold of the legacy getUserMedia, if present</span>
    <span style="color:var(--code-token-tag)">var</span> getUserMedia = navigator<span style="color:var(--code-token-punctuation)">.</span>webkitGetUserMedia || navigator<span style="color:var(--code-token-punctuation)">.</span>mozGetUserMedia<span style="color:var(--code-token-punctuation)">;</span>

    <span style="color:var(--code-token-comment)">// Some browsers just don't implement it - return a rejected promise with an error</span>
    <span style="color:var(--code-token-comment)">// to keep a consistent interface</span>
    <span style="color:var(--code-token-tag)">if</span> <span style="color:var(--code-token-punctuation)">(</span>!getUserMedia<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
      <span style="color:var(--code-token-tag)">return</span> Promise<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">reject</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">new</span> <span style="color:var(--code-token-attribute-name)">Error</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-attribute-value)">'getUserMedia is not implemented in this browser'</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
    <span style="color:var(--code-token-punctuation)">}</span>

    <span style="color:var(--code-token-comment)">// Otherwise, wrap the call to the old navigator.getUserMedia with a Promise</span>
    <span style="color:var(--code-token-tag)">return</span> <span style="color:var(--code-token-tag)">new</span> <span style="color:var(--code-token-attribute-name)">Promise</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>resolve<span style="color:var(--code-token-punctuation)">,</span> reject<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
      <span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">call</span><span style="color:var(--code-token-punctuation)">(</span>navigator<span style="color:var(--code-token-punctuation)">,</span> constraints<span style="color:var(--code-token-punctuation)">,</span> resolve<span style="color:var(--code-token-punctuation)">,</span> reject<span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
    <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-punctuation)">}</span>
<span style="color:var(--code-token-punctuation)">}</span>

navigator<span style="color:var(--code-token-punctuation)">.</span>mediaDevices<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getUserMedia</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">audio</span>: <span style="color:var(--code-token-attribute-value)">true</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-attribute-value)">true</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">then</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>stream<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  <span style="color:var(--code-token-tag)">var</span> video = document<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">querySelector</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-attribute-value)">'video'</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-comment)">// Older browsers may not have srcObject</span>
  <span style="color:var(--code-token-tag)">if</span> <span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-attribute-value)">"srcObject"</span> <span style="color:var(--code-token-tag)">in</span> video<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
    video<span style="color:var(--code-token-punctuation)">.</span>srcObject = stream<span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-tag)">else</span> <span style="color:var(--code-token-punctuation)">{</span>
    <span style="color:var(--code-token-comment)">// Avoid using this in new browsers, as it is going away.</span>
    video<span style="color:var(--code-token-punctuation)">.</span>src = window<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-value)">URL</span><span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">createObjectURL</span><span style="color:var(--code-token-punctuation)">(</span>stream<span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-punctuation)">}</span>
  video<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">onloadedmetadata</span> = <span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>e<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
    video<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">play</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
  <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>
<span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span>
<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">catch</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span>
  console<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">log</span><span style="color:var(--code-token-punctuation)">(</span>err<span style="color:var(--code-token-punctuation)">.</span>name + <span style="color:var(--code-token-attribute-value)">": "</span> + err<span style="color:var(--code-token-punctuation)">.</span>message<span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
<span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">;</span>
</code></span></span>

帧速率

在某些情况下,可能需要较低的帧速率,例如具有带宽限制的WebRTC传输。

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-tag)">var</span> constraints = <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">frameRate</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">ideal</span>: <span style="color:var(--code-token-attribute-value)">10</span><span style="color:var(--code-token-punctuation)">,</span> <span style="color:var(--code-token-attribute-name)">max</span>: <span style="color:var(--code-token-attribute-value)">15</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>
</code></span></span>

前置和后置摄像头

在手机上。

<span style="color:var(--code-default)"><span style="background-color:var(--code-background-block)"><code><span style="color:var(--code-token-tag)">var</span> front = <span style="color:var(--code-token-attribute-value)">false</span><span style="color:var(--code-token-punctuation)">;</span>
document<span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">getElementById</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-attribute-value)">'flip-button'</span><span style="color:var(--code-token-punctuation)">)</span><span style="color:var(--code-token-punctuation)">.</span><span style="color:var(--code-token-attribute-name)">onclick</span> = <span style="color:var(--code-token-tag)">function</span><span style="color:var(--code-token-punctuation)">(</span><span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">{</span> front = !front<span style="color:var(--code-token-punctuation)">;</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span>

<span style="color:var(--code-token-tag)">var</span> constraints = <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">video</span>: <span style="color:var(--code-token-punctuation)">{</span> <span style="color:var(--code-token-attribute-name)">facingMode</span>: <span style="color:var(--code-token-punctuation)">(</span>front? <span style="color:var(--code-token-attribute-value)">"user"</span> : <span style="color:var(--code-token-attribute-value)">"environment"</span><span style="color:var(--code-token-punctuation)">)</span> <span style="color:var(--code-token-punctuation)">}</span> <span style="color:var(--code-token-punctuation)">}</span><span style="color:var(--code-token-punctuation)">;</span></code></span></span>
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
navigator.mediaDevices.getUserMedia()方法用于调用设备的摄像头和麦克风。然而,由于不同浏览器的兼容性问题,可能会导致该方法在某些浏览器中无法正常工作。以下是解决navigator.mediaDevices.getUserMedia兼容问题的方法: 1. 检查浏览器兼容性:在调用navigator.mediaDevices.getUserMedia()之前,可以使用以下代码检查浏览器是否支持该方法: ```javascript if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { // 浏览器支持getUserMedia方法 } else { // 浏览器不支持getUserMedia方法 } ``` 2. 使用适配器库:为了解决不同浏览器之间的兼容性问题,可以使用适配器库,例如webrtc-adapter库。该库可以自动处理不同浏览器之间的差异,使得navigator.mediaDevices.getUserMedia()方法在所有浏览器中都能正常工作。你可以通过以下步骤使用webrtc-adapter库: a. 在HTML文件中引入webrtc-adapter库的脚本: ```html <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> ``` b. 在调用navigator.mediaDevices.getUserMedia()之前,不需要进行任何其他更改。 3. 检查设备权限:在某些情况下,navigator.mediaDevices.getUserMedia()方法可能无法正常工作是因为用户未授予访问摄像头和麦克风的权限。在调用该方法之前,可以使用以下代码检查用户是否已授予相应的权限: ```javascript navigator.permissions.query({ name: 'camera' }).then((permissionStatus) => { if (permissionStatus.state === 'granted') { // 用户已授予摄像头权限 } else { // 用户未授予摄像头权限 } }); ``` 如果用户未授予相应的权限,你可以提示用户授予权限或提供其他解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值