enumeratedevices() 返回 promise,需在 https 或 localhost 安全上下文中调用;过滤 kind 为 audioinput/videoinput 的设备,用 deviceid(非 label)传入 getusermedia 约束对象,并加 try/catch 处理断连。

直接调用 enumerateDevices() 就能拿到当前设备上所有可用的音视频输入输出源,但关键在于它返回的是 Promise,且结果依赖权限状态和设备物理连接情况——没授权或没插设备时,label 和 deviceId 都为空,不能直接用于后续采集。
确保在安全上下文里执行
该 API 只能在 HTTPS 或 localhost 环境中正常工作。非安全上下文下调用会静默失败或抛出 NotAllowedError。开发阶段建议用 http://localhost:8080 启服务,避免直接双击 HTML 打开。
正确处理 Promise 并过滤输入设备
返回的 MediaDeviceInfo[] 包含全部设备(含音频输出、视频输入等),需按 kind 过滤出真正可采集的源:
-
音频输入源:
kind === 'audioinput',对应麦克风或虚拟音频设备 -
视频输入源:
kind === 'videoinput',对应摄像头、采集卡或虚拟摄像头 - 跳过
audiooutput和未标 label 的条目(通常代表系统默认扬声器或未授权设备)
区分 deviceId 与 label 的用途
deviceId 是唯一且不可跨页面复用的字符串,必须传给 getUserMedia 才能指定设备;label 是用户可见名称(如“Logitech C920”),仅用于界面展示。注意:首次访问时若未授予权限,label 为空,此时只能靠 kind 和 groupId 做逻辑关联(例如同一物理设备的音/视频输入往往共享 groupId)。
结合 getUserMedia 实现设备切换
获取设备列表后,不能直接用 label 启动流,而应把选中的 deviceId 注入约束对象:
- 音频切换示例:
{ audio: { deviceId: { exact: selectedAudioId } } } - 视频切换示例:
{ video: { deviceId: { exact: selectedVideoId } } } - 为避免因设备断连导致报错,建议加
try/catch并 fallback 到无 deviceId 的基础请求










