必须先调用 getusermedia() 获取权限才能枚举媒体设备,否则返回空数组或 notallowederror;enumeratedevices() 返回 mediadeviceinfo 数组,含 deviceid、kind、label 等字段,label 常为空需依赖 deviceid;safari 不支持 audiooutput 枚举。

调用 enumerateDevices() 前必须先获得用户媒体权限
直接调用 enumerateDevices() 会返回空数组或抛出 NotAllowedError,因为浏览器禁止未获授权时暴露设备列表(隐私保护机制)。必须先触发一次 getUserMedia() 请求(哪怕只请求音频),才能解锁设备枚举能力。
- 最简可行做法:执行
navigator.mediaDevices.getUserMedia({ audio: true }).then(() => { /* 再调 enumerateDevices */ });视频权限同理,但仅音频开销更小 - 不能用
{ audio: false, video: false }—— 这不触发权限请求,也不会解锁枚举 - 若页面已通过其他方式(如之前调用过
getUserMedia)获得过权限,可跳过这步,但不可依赖
enumerateDevices() 返回的设备对象字段含义与过滤逻辑
返回的是 Promise,resolve 后是 MediaDeviceInfo[] 数组。每个设备有 deviceId、kind("audioinput" / "audiooutput" / "videoinput")、label(可能为空)、groupId 等字段。
-
label在无权限时为空字符串(即使已授权过,首次加载页面仍可能为空);需结合deviceId和kind做实际识别 - 区分输入输出:
device.kind === "audioinput"是麦克风,"audiooutput"是扬声器(注意:Safari 目前不支持audiooutput枚举) - 同一物理设备在不同页面可能有不同
deviceId,但groupId可用于跨设备关联(如笔记本内置麦克风和摄像头通常共享 groupId)
常见错误:拿不到 audiooutput 设备或 label 始终为空
这不是代码写错,而是浏览器兼容性与权限模型限制导致的典型现象。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- Safari 完全不支持
audiooutput枚举(截至 Safari 17.5),调用后数组里不会有kind === "audiooutput"的项 - Chrome / Edge 中,
label为空是常态 —— 用户必须在系统设置中开启「网站可访问设备名称」(macOS 需勾选“允许网页查看和控制音频输入/输出设备”);Windows 则依赖系统隐私设置是否允许浏览器访问麦克风/扬声器 - 即使 label 为空,只要
deviceId存在,仍可用于setSinkId()或getUserMedia(),不必强依赖 label 显示
完整可运行示例(含错误处理与设备类型过滤)
<script>
async function listDevices() {
try {
// 必须先获取权限
await navigator.mediaDevices.getUserMedia({ audio: true });
<pre class='brush:php;toolbar:false;'>const devices = await navigator.mediaDevices.enumerateDevices();
const inputs = devices.filter(d => d.kind === 'audioinput');
const outputs = devices.filter(d => d.kind === 'audiooutput');
const cameras = devices.filter(d => d.kind === 'videoinput');
console.log('Microphones:', inputs);
console.log('Speakers:', outputs);
console.log('Cameras:', cameras);</script>
} catch (err) { console.error('Device enumeration failed:', err.name, err.message); // 常见 err.name:NotAllowedError、SecurityError、NotFoundError } } listDevices();
注意:这个函数需在用户交互(如点击按钮)后调用,否则 Chrome 会拒绝 getUserMedia 请求(Autoplay Policy);Safari 对交互要求更严格,建议始终绑定到 button click。
设备列表不是静态快照 —— 插拔 USB 设备、切换蓝牙耳机都会触发 devicechange 事件,但该事件不提供变更详情,只能重新调用 enumerateDevices() 获取全量更新。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










