Signatur
Beschreibung
enumerateDevices() ist eine Methode der Schnittstelle MediaDevices, die über navigator.mediaDevices erreichbar ist. Sie gibt ein Promise zurück, das mit einem Array von MediaDeviceInfo-Objekten erfüllt wird. Jedes Objekt beschreibt ein Gerät mit den Eigenschaften deviceId, groupId, kind ("audioinput", "videoinput" oder "audiooutput") und label.
Typische Anwendungen sind Geräteauswahl-Menüs in Videokonferenz-Apps, das Umschalten zwischen Front- und Rückkamera oder die Wahl des Audio-Ausgabegeräts über HTMLMediaElement.setSinkId(). Mit der ermittelten deviceId kann man anschließend gezielt über getUserMedia({ video: { deviceId: { exact: id } } }) ein bestimmtes Gerät öffnen.
Aus Datenschutzgründen sind die Ergebnisse eingeschränkt, solange die Seite keine Medienberechtigung hat: label ist dann ein leerer String, deviceId kann leer sein, und manche Browser melden pro Gerätetyp nur einen einzigen Platzhalter-Eintrag. Erst nach einem erfolgreichen getUserMedia()-Aufruf werden vollständige Informationen geliefert.
Um auf das An- und Abstecken von Geräten zu reagieren, lauscht man auf das Ereignis devicechange von navigator.mediaDevices und ruft enumerateDevices() erneut auf.
Rückgabewert
MediaDeviceInfo-Objekten (bzw. InputDeviceInfo für Eingabegeräte) erfüllt wird. Sind keine Geräte vorhanden oder ist der Zugriff per Berechtigungsrichtlinie gesperrt, ist das Array leer.Beispiele
Alle Geräte auflisten
const listDevices = async () => {
if (!navigator.mediaDevices?.enumerateDevices) {
console.warn('enumerateDevices() wird nicht unterstützt');
return;
}
const devices = await navigator.mediaDevices.enumerateDevices();
for (const { kind, label, deviceId } of devices) {
console.log(`${kind}: ${label || '(ohne Label)'} id=${deviceId}`);
}
};
listDevices();
Kamera-Auswahl nach Berechtigung befüllen
const select = document.querySelector('#camera-select');
const video = document.querySelector('video');
const fillCameraSelect = async () => {
// Erst Berechtigung holen, damit Labels sichtbar werden
const tmp = await navigator.mediaDevices.getUserMedia({ video: true });
tmp.getTracks().forEach((t) => t.stop());
const devices = await navigator.mediaDevices.enumerateDevices();
const cams = devices.filter((d) => d.kind === 'videoinput');
select.replaceChildren(
...cams.map((cam, i) => new Option(cam.label || `Kamera ${i + 1}`, cam.deviceId))
);
};
select.addEventListener('change', async () => {
video.srcObject?.getTracks().forEach((t) => t.stop());
video.srcObject = await navigator.mediaDevices.getUserMedia({
video: { deviceId: { exact: select.value } }
});
});
fillCameraSelect().catch((err) => console.error('Kein Kamerazugriff:', err.name));
Auf An- und Abstecken von Geräten reagieren
const countDevices = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
const count = (kind) => devices.filter((d) => d.kind === kind).length;
console.log(`Mikrofone: ${count('audioinput')}, Kameras: ${count('videoinput')}, Ausgaben: ${count('audiooutput')}`);
};
navigator.mediaDevices.addEventListener('devicechange', countDevices);
countDevices();
// Wichtig · Fallstricke
- Sicherer Kontext erforderlich:
navigator.mediaDevicesexistiert nur unter HTTPS oderlocalhost; auf HTTP ist esundefined. - Leere Labels: Ohne erteilte Kamera-/Mikrofon-Berechtigung ist
labelleer und die Liste ggf. auf einen Eintrag pro Typ reduziert. Nicht aus leeren Labels auf fehlende Geräte schließen. deviceIdist pro Ursprung eindeutig und wird beim Löschen der Website-Daten neu vergeben. Zum Speichern von Benutzerpräferenzen inlocalStoragegeeignet, aber immer auf Existenz prüfen undlabelals Fallback nutzen.audiooutput: Firefox und Safari listen Ausgabegeräte teilweise nicht oder erst nachselectAudioOutput()/Berechtigung;setSinkId()ist nicht überall verfügbar.- Die Pseudo-IDs
"default"und"communications"(Chrome unter Windows) verweisen auf reale Geräte, die ebenfalls in der Liste auftauchen – beim Zählen ggf. übergroupIddeduplizieren. - In Iframes muss die Berechtigungsrichtlinie (
allow="camera; microphone") gesetzt sein, sonst fehlen die entsprechenden Geräte. - Die Methode ist nur im Dokumentkontext verfügbar, nicht in Web Workern.