MediaDevices: devicechange 事件

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

當系統連線或移除諸如攝像頭、麥克風或揚聲器之類的媒體裝置時,會向 MediaDevices 例項傳送 devicechange 事件。

此事件不可取消,也不會冒泡。

語法

在諸如 addEventListener() 之類的方法中使用事件名稱,或設定事件處理程式屬性。

js
addEventListener("devicechange", (event) => { })

ondevicechange = (event) => { }

事件型別

一個通用的 Event

示例

在此示例中,我們建立了一個名為 updateDeviceList() 的函式。該函式在 MediaDevices.getUserMedia() 成功獲取到流時呼叫一次,之後每當裝置列表發生變化時都會呼叫。它會在瀏覽器視窗中顯示兩個列表:一個音訊裝置列表,一個影片裝置列表,其中包含裝置標籤(名稱)以及它是輸入裝置還是輸出裝置。由於示例為 devicechange 事件提供了處理程式,因此每次向執行示例的裝置新增或移除媒體裝置時,列表都會重新整理。

我們設定了全域性變數,這些變數包含用於列出音訊和影片裝置的 <ul> 元素的引用。

js
const audioList = document.getElementById("audioList");
const videoList = document.getElementById("videoList");

獲取並繪製裝置列表

現在讓我們看看 updateDeviceList() 本身。每當我們要獲取當前媒體裝置列表並使用該資訊更新顯示的音訊和影片裝置列表時,都會呼叫此方法。

js
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() 完全由對 navigator.mediaDevices 屬性中引用的 MediaDevices 物件呼叫 enumerateDevices() 函式以及在 promise 被滿足時執行的程式碼組成。當裝置列表準備就緒時,會呼叫滿足處理程式。列表以 MediaDeviceInfo 物件陣列的形式傳遞到滿足處理程式中,每個物件描述一個媒體輸入或輸出裝置。

使用 forEach() 迴圈掃描所有裝置。對於每個裝置,我們建立一個新的 <li> 物件,用於將其顯示給使用者。

let [kind, type, direction] = device.kind.match(/(\w+)(input|output)/i); 這行程式碼值得特別注意。它使用 解構賦值String.match() 返回的陣列中的前三個元素的值賦給變數 kindtypedirection。我們這樣做是因為 MediaDeviceInfo.kind 的值是一個單一字串,其中同時包含媒體型別和媒體流動的方向,例如“audioinput”或“videooutput”。因此,這一行會提取出型別(“audio”或“video”)和方向(“input”或“output”),以便它們可用於構建列表中顯示的字串。

一旦字串被組裝起來,其中包含裝置名稱(粗體顯示)和方向(括號內顯示),它就會透過根據裝置型別呼叫 audioListvideoList 上的 appendChild() 來附加到相應的列表中。

處理裝置列表更改

我們在兩個地方呼叫 updateDeviceList()。第一個是在 getUserMedia() promise 的滿足處理程式中,以便在流開啟時最初填充列表。第二個是在此 devicechange 事件的事件處理程式中。

js
navigator.mediaDevices.ondevicechange = (event) => {
  updateDeviceList();
};

有了這段程式碼,每次使用者插入攝像頭、麥克風或其他媒體裝置,或者開啟或關閉它們時,我們都會呼叫 updateDeviceList() 來重繪已連線裝置的列表。

結果

規範

規範
媒體捕獲和流
# event-mediadevices-devicechange
媒體捕獲和流
# dom-mediadevices-ondevicechange

瀏覽器相容性