MediaDevices:devicechange 事件
每当将媒体设备(例如摄像头、麦克风或扬声器)连接到系统或从系统中移除时,都会向MediaDevices
实例发送devicechange
事件。
此事件不可取消,也不冒泡。
语法
在诸如addEventListener()
之类的 方法中使用事件名称,或设置事件处理程序属性。
addEventListener("devicechange", (event) => {});
ondevicechange = (event) => {};
事件类型
一个通用的Event
。
示例
在此示例中,我们创建一个名为 updateDeviceList()
的函数,该函数在MediaDevices.getUserMedia()
成功获取流时调用一次,然后在设备列表发生更改时调用。它在浏览器窗口中显示两个列表:一个音频设备列表和一个视频设备列表,两个列表都显示设备的标签(名称)以及它是输入设备还是输出设备。由于该示例为 devicechange
事件提供了一个处理程序,因此每次将媒体设备连接到或从运行示例的设备上移除时,列表都会刷新。
我们设置了全局变量,这些变量包含对用于列出音频和视频设备的<ul>
元素的引用
const audioList = document.getElementById("audioList");
const videoList = document.getElementById("videoList");
获取和绘制设备列表
现在让我们看一下 updateDeviceList()
本身。每当我们想要获取当前的媒体设备列表,然后使用该信息更新显示的音频和视频设备列表时,都会调用此方法。
function updateDeviceList() {
navigator.mediaDevices.enumerateDevices().then((devices) => {
audioList.textContent = "";
videoList.textContent = "";
devices.forEach((device) => {
const elem = document.createElement("li");
const [kind, type, direction] = device.kind.match(/(\w+)(input|output)/i);
elem.innerHTML = `<strong>${device.label}</strong> (${direction})`;
if (type === "audio") {
audioList.appendChild(elem);
} else if (type === "video") {
videoList.appendChild(elem);
}
});
});
}
updateDeviceList()
完全由对enumerateDevices()
函数(在navigator.mediaDevices
属性中引用的MediaDevices
对象上)的调用以及 enumerateDevices()
返回的promise
完成时运行的代码组成。当设备列表准备就绪时,将调用完成处理程序。该列表作为MediaDeviceInfo
对象的数组传递到完成处理程序中,每个对象描述一个媒体输入或输出设备。
一个forEach()
循环用于扫描所有设备。对于每个设备,我们创建一个新的<li>
对象,用于将其显示给用户。
let [kind, type, direction] = device.kind.match(/(\w+)(input|output)/i);
这一行值得特别注意。它使用解构赋值将String.match()
返回的数组中的前三个项目的value分配给变量 kind
、type
和 direction
。我们这样做是因为MediaDeviceInfo.kind
的值是一个包含媒体类型和媒体流方向(例如“audioinput”或“videooutput”)的单个字符串。然后,此行提取类型(“audio”或“video”)和方向(“input”或“output”),以便可以将其用于构建显示在列表中的字符串。
组装好字符串后,该字符串包含设备名称(加粗)和方向(括号内),然后通过在相应的 audioList
或 videoList
上调用appendChild()
将其附加到相应的列表中,具体取决于设备类型。
处理设备列表更改
我们在两个地方调用 updateDeviceList()
。第一个是在getUserMedia()
promise 的完成处理程序中,在打开流时最初填充列表。第二个是在此 devicechange
事件的事件处理程序中
navigator.mediaDevices.ondevicechange = (event) => {
updateDeviceList();
};
有了这段代码,每次用户插入摄像头、麦克风或其他媒体设备,或打开或关闭某个设备时,我们都会调用 updateDeviceList()
来重新绘制连接设备的列表。
结果
规范
规范 |
---|
媒体捕获和流 # event-mediadevices-devicechange |
媒体捕获和流 # dom-mediadevices-ondevicechange |
浏览器兼容性
BCD 表格仅在启用了 JavaScript 的浏览器中加载。