--- title: MediaDevices.ondevicechange slug: Web/API/MediaDevices/devicechange_event translation_of: Web/API/MediaDevices/ondevicechange original_slug: Web/API/MediaDevices/ondevicechange ---
{{APIRef("Media Capture and Streams")}}
MediaDevices.ondevicechangeプロパティは{{event("Event_handlers", "event handler")}}であり、{{domxref("MediaDevices")}}インスタンスで{{event("devicechange")}}が発生した時に呼び出される関数です。このイベントは、{{Glossary("user agent")}}、Webサイト、アプリケーションによって利用可能なメディアデバイスの一覧が変更された時に発生します。更新された利用可能デバイスの一覧は{{domxref("MediaDevices.enumerateDevices", "enumerateDevices()")}}によっていつでも取得することができます。
MediaDevices.ondevicechange = eventHandler;
{{event("devicechange")}}イベントが発生したことを示す{{domxref("Event")}}オブジェクトを入力として受け付ける関数を指定してください。このイベントオブジェクトには、変更に関する情報が含まれていませんので、更新されたデバイスの一覧を取得したい場合は、{{domxref("MediaDevices.enumerateDevices", "enumerateDevices()")}}を呼び出してください。
この例では、updateDeviceList()という関数があり、この関数は{{domxref("MediaDevices.getUserMedia()")}}が成功して、ストリームを取得できた時に一度だけ呼び出され、その後デバイスの一覧に変更があった場合も複数回呼び出されます。この関数は、ブラウザウィンドウに2つの一覧を出力します。1つは、オーディオデバイスの一覧であり、もう1つはビデオデバイスの一覧です。これら2つのリストは、デバイスラベル (名前)とこのデバイスが入力か出力であるかを示すものです。この例では、{{event("devicechange")}}イベントのハンドラを設定しているので、実行中にデバイスが接続または接続を解除されるたびに一覧が更新されます。
<p>Click the start button below to begin the demonstration.</p> <div id="startButton" class="button"> Start </div> <video id="video" width="160" height="120" autoplay></video><br> <div class="left"> <h2>Audio devices:</h2> <ul class="deviceList" id="audioList"></ul> </div> <div class="right"> <h2>Video devices:</h2> <ul class="deviceList" id="videoList"></ul> </div> <div id="log"></div>
body {
font: 14px "Open Sans", "Arial", sans-serif;
}
video {
margin-top: 20px;
border: 1px solid black;
}
.button {
cursor: pointer;
width: 160px;
border: 1px solid black;
font-size: 16px;
text-align: center;
padding-top: 2px;
padding-bottom: 4px;
color: white;
background-color: darkgreen;
}
h2 {
margin-bottom: 4px;
}
.left {
float:left;
width: 48%;
margin-right: 2%
}
.right {
float:right;
width: 48%;
margin-left: 2%
}
.deviceList {
border: 1px solid black;
list-style-type: none;
margin-top: 2px;
padding: 6px;
}
下のコードは、ondevicechangeと直接関係がないため詳細を省きます。
let videoElement = document.getElementById("video");
let logElement = document.getElementById("log");
function log(msg) {
logElement.innerHTML += msg + "<br>";
}
document.getElementById("startButton").addEventListener("click", function() {
navigator.mediaDevices.getUserMedia({
video: {
width: 160,
height: 120,
frameRate: 30
},
audio: {
sampleRate: 44100,
sampleSize: 16,
volume: 0.25
}
}).then(stream => {
videoElement.srcObject = stream;
updateDeviceList();
})
.catch(err => log(err.name + ": " + err.message));
}, false);
オーディオとビデオデバイスの一覧に使用される{{HTMLElement("ul")}}要素への参照を保持するためのグローバル変数を用意します。
let audioList = document.getElementById("audioList");
let videoList = document.getElementById("videoList");
updateDeviceList()メソッドでは、現在のメディアデバイスの一覧を取得した後、先ほど用意したグローバル変数を用いて、表示されているオーディオとビデオのデバイス一覧を更新します。
function updateDeviceList() {
navigator.mediaDevices.enumerateDevices()
.then(function(devices) {
audioList.innerHTML = "";
videoList.innerHTML = "";
devices.forEach(function(device) {
let elem = document.createElement("li");
let [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()は、{{domxref("navigator.mediaDevices")}}プロパティから参照できる{{domxref("MediaDevices")}}オブジェクトにある{{domxref("MediaDevices.enumerateDevices", "enumerateDevices()")}}関数の呼び出しから構成されます。コードが実行されるのは、enumerateDevices()によって返された{{jsxref("promise")}}が完了した時です。デバイス一覧の準備ができると、完了ハンドラが呼び出されます。このデバイス一覧は、完了ハンドラの引数として{{domxref("MediaDeviceInfo")}}オブジェクトの配列で渡されます。この配列のそれぞれの要素は、1つのメディア入力デバイスまたは出力デバイスについての情報を含みます。
すべてのデバイスの情報を出力するために、{{jsxref("Array.forEach", "forEach()")}}ループを使用します。それぞれのデバイスで、ユーザへこのデバイス情報を見せるために新しい{{HTMLElement("li")}}オブジェクトを作成します。
let [kind, type, direction] = device.kind.match(/(\w+)(input|output)/i);の行について詳しく説明します。ここでは分割代入 (ECMAScript 6の新しい機能)を使用しており、{{jsxref("String.match()")}}によって返された配列の値をkind、type、directionの変数へ代入しています。なぜこのようなことをするのかというと、{{domxref("MediaDeviceInfo.kind")}}の文字列は、"audioinput"や"videooutput"のように、メディアタイプとメディアフローの向きの2つの情報を含んでいるためです。この行で、タイプ("audio"または"video")と方向("input"と"output")を取り出すことで、リストに表示する文字列を作成することができます。
太字のデバイス名と括弧で囲まれた方向を含む文字列が作成されると、デバイスタイプに基づいてaudioListまたはvideoList対応する一覧へ{{domxref("Node.appendChild", "appendChild()")}}の呼び出しによって追加されます。
updateDeviceList()は2箇所から呼び出されます。1箇所目は{{domxref("MediaDevices.getUserMedia", "getUserMedia()")}}のpromiseの完了ハンドラであり、ストリームが開かれた時に最初に一覧を埋めます。2箇所目は{{event("devicechange")}}のイベントハンドラからです。
navigator.mediaDevices.ondevicechange = function(event) {
updateDeviceList();
}
このコードでは、ユーザがカメラ、マイク、他のメディアデバイスを接続したり、電源を入れたり、電源を切ったりする度に、updateDeviceList()を呼び出し接続されたデバイス一覧を再描画します。
{{ EmbedLiveSample('Example', 600, 460) }}
| 仕様 | 状況 | コメント |
|---|---|---|
| {{ SpecName('Media Capture', '#dom-mediadevices-ondevicechange', 'ondevicechange') }} | {{ Spec2('Media Capture') }} | 初版 |
{{Compat("api.MediaDevices.ondevicechange")}}