Start · Sprachen · JavaScript · Referenz · MediaDevices

MediaDevices

Schnittstelle

Stellt über <code>navigator.mediaDevices</code> Zugriff auf Kameras, Mikrofone und Bildschirmfreigabe bereit und listet verfügbare Medienein- und -ausgabegeräte auf.

seit JavaScript Baseline: alle modernen Browser (getDisplayMedia a Kategorie: webapi

Signatur

interface MediaDevices extends EventTarget

Beschreibung

Das Interface MediaDevices gehört zur Media Capture and Streams API und ist der zentrale Einstiegspunkt für den Zugriff auf Medienhardware im Browser. Es gibt keinen öffentlichen Konstruktor. Man erhält die einzige Instanz immer über navigator.mediaDevices.

Die wichtigsten Methoden:

  • getUserMedia(constraints): fragt die Berechtigung für Kamera und/oder Mikrofon an und liefert einen MediaStream.
  • getDisplayMedia(options): startet eine Bildschirm-, Fenster- oder Tab-Freigabe.
  • enumerateDevices(): liefert eine Liste von MediaDeviceInfo-Objekten (Kameras, Mikrofone, Audioausgänge).
  • getSupportedConstraints(): gibt an, welche Constraints (z. B. width, facingMode, echoCancellation) der Browser versteht.
  • selectAudioOutput() (experimentell): lässt Nutzende einen Audioausgang auswählen.

Da MediaDevices von EventTarget erbt, feuert es das Ereignis devicechange, wenn ein Gerät angeschlossen oder entfernt wird. Darauf reagiert man mit addEventListener("devicechange", …) oder über die Eigenschaft ondevicechange. Einsatzgebiete sind Videokonferenzen (WebRTC), Foto- und Scanner-Funktionen, Audioaufnahmen mit MediaRecorder und Screencasting.

Alle Methoden zur Aufnahme arbeiten asynchron mit Promises und benötigen einen sicheren Kontext (HTTPS oder localhost). Außerdem muss der Nutzer die Berechtigung erteilen. Deshalb gehört eine saubere Fehlerbehandlung (NotAllowedError, NotFoundError, OverconstrainedError) immer dazu.

Parameter

Name Typ Default Beschreibung
$constraints MediaStreamConstraints {} Für getUserMedia(): Objekt mit audio und/oder video (jeweils boolean oder MediaTrackConstraints). Mindestens eines davon muss gesetzt sein.
$options DisplayMediaStreamOptions { video: true } Für getDisplayMedia(): steuert video, audio und Hinweise wie preferCurrentTab oder selfBrowserSurface.

Beispiele

Instanz holen und Kamera im Video-Element anzeigen

const video = document.querySelector('video');

const startCamera = async () => {
  if (!navigator.mediaDevices?.getUserMedia) {
    console.warn('getUserMedia wird nicht unterstützt (kein sicherer Kontext?)');
    return;
  }
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      video: { width: { ideal: 1280 }, height: { ideal: 720 }, facingMode: 'user' },
      audio: false
    });
    video.srcObject = stream;
    await video.play();
    console.log('Kamera aktiv:', stream.getVideoTracks()[0].label);
  } catch (err) {
    if (err.name === 'NotAllowedError') console.error('Zugriff verweigert');
    else if (err.name === 'NotFoundError') console.error('Keine Kamera gefunden');
    else console.error(err);
  }
};

startCamera();
Kamera aktiv: FaceTime HD Camera

Geräte auflisten und bei Änderungen aktualisieren

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}`);
  cams.forEach(c => console.log(c.deviceId, c.label || '(Label erst nach Freigabe)'));
};

const onChange = () => {
  console.log('Gerät angeschlossen/entfernt');
  listDevices();
};

navigator.mediaDevices.addEventListener('devicechange', onChange);
listDevices();

// Später wieder abmelden:
// navigator.mediaDevices.removeEventListener('devicechange', onChange);
// Alternativ: navigator.mediaDevices.ondevicechange = onChange;
Kameras: 1, Mikrofone: 2

Bildschirmfreigabe starten und Ende erkennen

const shareButton = document.querySelector('#share');

shareButton.addEventListener('click', async () => {
  try {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      video: { frameRate: 30 },
      audio: true
    });
    const [track] = stream.getVideoTracks();
    console.log('Freigabe:', track.getSettings().displaySurface);
    // Nutzer beendet die Freigabe über die Browser-Leiste
    track.addEventListener('ended', () => console.log('Freigabe beendet'));
  } catch (err) {
    console.error('Freigabe abgebrochen:', err.name);
  }
});
Freigabe: monitor

Unterstützte Constraints prüfen

const supported = navigator.mediaDevices.getSupportedConstraints();
const audio = {
  echoCancellation: supported.echoCancellation ? true : undefined,
  noiseSuppression: supported.noiseSuppression ? true : undefined
};
console.log(supported.facingMode, supported.echoCancellation);

const stream = await navigator.mediaDevices.getUserMedia({ audio });
console.log(stream.getAudioTracks()[0].getSettings());
true true { deviceId: "…", echoCancellation: true, noiseSuppression: true, … }

// Wichtig · Fallstricke

  • Nur im sicheren Kontext: Auf reinem HTTP (außer localhost) ist navigator.mediaDevices undefined. Deshalb vor dem Zugriff mit navigator.mediaDevices?.getUserMedia prüfen.
  • Berechtigungen und Datenschutz: enumerateDevices() gibt label und oft auch deviceId erst zurück, nachdem eine Berechtigung erteilt wurde. In iframes muss der Zugriff über das Attribut allow="camera; microphone; display-capture" bzw. die Permissions Policy erlaubt sein.
  • Nutzeraktion nötig: getDisplayMedia() muss durch eine Nutzeraktion wie einen Klick ausgelöst werden. Auf den meisten mobilen Browsern wird es nicht unterstützt.
  • Ressourcen freigeben: Die Kamera-LED bleibt an, bis alle Tracks mit stream.getTracks().forEach(t => t.stop()) beendet werden.
  • Constraints: exact-Werte, die das Gerät nicht erfüllen kann, führen zu einem OverconstrainedError. Besser ist ideal.
  • Die veraltete Funktion navigator.getUserMedia() (mit Callbacks) sollte nicht mehr verwendet werden. selectAudioOutput() ist experimentell und wird derzeit fast nur von Firefox unterstützt.