Start · Sprachen · JavaScript · Referenz · MediaDevices: devicechange

MediaDevices: devicechange

Ereignis

Wird an <code>navigator.mediaDevices</code> gesendet, sobald eine Kamera, ein Mikrofon oder ein Audioausgabegerät angeschlossen oder entfernt wird.

seit JavaScript Baseline: Chrome 57+, Firefox 52+, Safari 11+, Edg Kategorie: webapi

Signatur

navigator.mediaDevices.addEventListener("devicechange", handler)

Beschreibung

Das Ereignis devicechange wird an das MediaDevices-Objekt (navigator.mediaDevices) gesendet, wenn sich die Liste der verfügbaren Mediengeräte ändert. Das passiert zum Beispiel, wenn ein USB-Headset eingesteckt, eine Webcam abgezogen oder ein Bluetooth-Lautsprecher verbunden wird. Auch wenn sich Geräteberechtigungen ändern, kann das Ereignis ausgelöst werden.

Das Ereignis enthält keine Angaben dazu, welches Gerät hinzugekommen oder weggefallen ist. Es ist ein einfaches Event. Um die aktuelle Liste zu bekommen, rufen Sie im Handler navigator.mediaDevices.enumerateDevices() erneut auf und vergleichen das Ergebnis mit dem vorherigen Stand.

Typische Anwendungen sind Geräteauswahl-Menüs in Videokonferenz-Apps, die automatisch aktualisiert werden, ein automatischer Wechsel auf ein neu angeschlossenes Headset oder ein Rückfall auf ein anderes Mikrofon, wenn das aktive Gerät entfernt wurde.

Sie können den Handler mit addEventListener("devicechange", handler) registrieren oder über die Eigenschaft navigator.mediaDevices.ondevicechange setzen. Über die Eigenschaft ist immer nur ein Handler möglich, und eine neue Zuweisung überschreibt den alten.

Parameter

Name Typ Default Beschreibung
$type Pflicht string Der Ereignisname, immer "devicechange".
$handler Pflicht (event: Event) => void Rückruffunktion, die ein einfaches Event ohne Geräteinformationen bekommt.
$options boolean | AddEventListenerOptions false Optionen wie once oder signal (z. B. ein AbortSignal, um den Listener wieder zu entfernen).

Rückgabewert

Typ
void
Beschreibung
addEventListener gibt nichts zurück. Der Handler bekommt ein Event-Objekt mit type === "devicechange".

Beispiele

Geräteliste bei Änderungen neu laden (addEventListener)

const listDevices = async () => {
  const devices = await navigator.mediaDevices.enumerateDevices();
  const cams = devices.filter((d) => d.kind === 'videoinput');
  const mics = devices.filter((d) => d.kind === 'audioinput');
  console.log(`Kameras: ${cams.length}, Mikrofone: ${mics.length}`);
};

navigator.mediaDevices.addEventListener('devicechange', listDevices);
listDevices(); // Anfangszustand
Kameras: 1, Mikrofone: 2 // nach Einstecken eines USB-Headsets: Kameras: 1, Mikrofone: 3

Hinzugefügte und entfernte Geräte ermitteln

let known = new Map();

const snapshot = async () => {
  const devices = await navigator.mediaDevices.enumerateDevices();
  return new Map(devices.map((d) => [d.deviceId + d.kind, d]));
};

const onChange = async () => {
  const current = await snapshot();
  for (const [id, d] of current) {
    if (!known.has(id)) console.log('Neu:', d.kind, d.label || '(ohne Name)');
  }
  for (const [id, d] of known) {
    if (!current.has(id)) console.log('Entfernt:', d.kind, d.label || '(ohne Name)');
  }
  known = current;
};

known = await snapshot();
navigator.mediaDevices.addEventListener('devicechange', onChange);
Neu: audioinput USB Headset Mikrofon Neu: audiooutput USB Headset Lautsprecher

Auf anderes Mikrofon ausweichen, wenn das aktive entfernt wurde

let stream = await navigator.mediaDevices.getUserMedia({ audio: true });

navigator.mediaDevices.ondevicechange = async () => {
  const [track] = stream.getAudioTracks();
  if (track.readyState === 'ended') {
    console.log('Aktives Mikrofon verloren – wechsle auf Standardgerät');
    stream = await navigator.mediaDevices.getUserMedia({ audio: true });
  }
};
Aktives Mikrofon verloren – wechsle auf Standardgerät

Listener per AbortController entfernen

const controller = new AbortController();

navigator.mediaDevices.addEventListener(
  'devicechange',
  () => console.log('Geräteliste geändert'),
  { signal: controller.signal }
);

// Beim Verlassen der Ansicht aufräumen:
controller.abort();
// Alternativ bei der Eigenschaft:
navigator.mediaDevices.ondevicechange = null;

// Wichtig · Fallstricke

  • Keine Details im Ereignis: Das Event sagt nicht, welches Gerät betroffen ist. Rufen Sie immer enumerateDevices() auf und vergleichen Sie selbst.
  • Mehrfache Auslösung: Ein einziges Headset kann mehrere Ereignisse direkt nacheinander auslösen, etwa für Ein- und Ausgabe getrennt. Fassen Sie die Ereignisse bei Bedarf mit einem kurzen Debounce zusammen.
  • Datenschutz: Ohne erteilte Kamera- oder Mikrofonberechtigung sind label leer und deviceId oft leer oder anonymisiert. Manche Browser lösen devicechange erst aus, wenn die Seite sichtbar ist oder bereits eine Berechtigung hat. Das soll verhindern, dass Nutzer über ihre Hardware verfolgt werden (Fingerprinting).
  • Sicherer Kontext: navigator.mediaDevices gibt es nur unter HTTPS oder auf localhost. Unter HTTP ist es undefined, und addEventListener wirft dann einen Fehler.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Safari unterstützt es ab Version 11. Audioausgabegeräte (audiooutput) werden in Firefox und Safari nur eingeschränkt aufgelistet.
  • Ein entferntes aktives Gerät beendet den zugehörigen MediaStreamTrack (ended-Ereignis). Oft ist es zuverlässiger, zusätzlich darauf zu reagieren.