getUserMedia
接口详细文档见 developer.mozilla.org/zh-CN/docs/…
官方已有的说明就不重复了,这里主要记录一下 getUserMedia
接口实际使用中碰到的问题以及需要注意的点,碰到新问题及时更新~
一、未授权时调用 enumerateDevices
在使用 getUserMedia 获取网站访问摄像头/麦克风权限前调用 enumerateDevices 来获取设备列表时,有两种不同的问题表现形式:
- 在 windows 上的 浏览器和 linux 下的 firefox 中, enumerateDevices 可以获取到所有的麦克风/摄像头设备,但是 label 相关字段为空字符串
- 在 linux 下的 chrome 中,enumerateDevices 无法获取到所有的麦克风/摄像头设备,获取到的设备信息中除了 label 等信息外 deviceId 字段也是空串,只有一个 groupId 信息
第一种情况只影响显示不影响使用,第二种情况影响使用。
PS: 第二种情况的表现形式完整的环境如下:在 Fadora34 中使用 chrome,摄像头/麦克风是阿卡西斯的 4 路 SDI 采集卡。时间有限,没有遍历各种情况,找到问题解决办法后就没有继续研究了。
二、获取摄像头/麦克风权限
使用下面的代码即可向用户请求使用摄像头/麦克风权限,如果用户第一次访问会在右上角弹出权限允许窗口
navigator.mediaDevices.getUserMedia({ video: true, audio: true });
当用户终端没有麦克风或者摄像头时,使用上面的方式浏览器会直接返回 NotFoundError 异常而不会弹出权限允许窗口,这种情况下需要注意遍历只有摄像头或者只有麦克风的情况。
完整的代码可以参考我写的另外一篇文章:获取摄像头/麦克风权限
三、指定摄像头分辨率
获取视频时可以通过下面的方式指定视频的分辨率
navigator.mediaDevices.getUserMedia({ video: { width: 1920, height: 1080 }, audio: false });
浏览器会试着满足这个请求参数,但是如果无法准确满足此请求中参数要求或者用户选择覆盖了请求中的参数时,有可能返回其它的分辨率。
这种情况下,如果这个摄像头可用就可以拿到视频,但是视频的分辨率不一定是指定的。特别要注意是如果已经请求了一个视频未释放的情况下大概率会获取到之前分辨率的视频,涉及到分辨率选择的话一定要先把之前的流释放掉。
width/height
属性除了上面这种方式指定,还可以通对象去指定,强制要求获取特定的尺寸时,可以使用关键字 min
, max
, 或者 exact
navigator.mediaDevices.getUserMedia({
video: {
width: { min: 1280, max: 1920 },
height: { min: 720, max: 1280 },
},
audio: false,
});
如果摄像头不支持请求的分辨率,返回的 Promise 会处于 rejected 状态,NotFoundError 作为 rejected 回调的参数,而且用户将不会得到要求授权的提示。
这种情况下,如果摄像头支持的分辨率不在范围内会获取不到视频
width: { exact: 1920 }
和 width: { min: 1920, max: 1920 }
等价。
当请求包含一个 ideal(应用最理想的)值时,这个值有着更高的权重,意味着浏览器会先尝试找到最接近指定的理想值的设定或者摄像头(如果设备拥有不止一个摄像头)。
ideal
有着更高的权重,会导致指定的 deviceId
无效,慎用!!!
四、使用前置摄像头
使用前置/后置摄像头时需要注意不能携带 deviceId
参数
navigator.mediaDevices.getUserMedia({
video: {
facingMode: "user",
},
audio: false,
});
五、麦克风自动增益 autoGainControl
使用过程中,有些麦克风硬件自带自动增益,这种情况下浏览器的自动增益属性也打开的话,两者之间会相互影响,导致拾音的质量非常差,这种情况下关闭任何一个自动增益即可。