Signatur
Beschreibung
navigator.mediaDevices.getUserMedia() ist der Standardweg, um im Browser auf Kamera und Mikrofon zuzugreifen. Die Methode zeigt dem Benutzer einen Berechtigungsdialog. Stimmt er zu, wird das Promise mit einem MediaStream erfüllt, der je nach Anforderung Video- und/oder Audiospuren (MediaStreamTrack) enthält.
Welche Medien man möchte und in welcher Qualität, legt man über ein Constraints-Objekt fest. Mit { video: true, audio: true } fordert man einfach beide Gerätearten an. Man kann aber auch genauer werden: Auflösung, Bildrate, Front- oder Rückkamera (facingMode), eine bestimmte deviceId oder Audio-Optionen wie echoCancellation. Werte lassen sich als ideal (Wunsch), exact (Pflicht) oder als Bereich mit min/max angeben.
Typische Einsätze sind Videotelefonie mit WebRTC (RTCPeerConnection), Fotos direkt im Browser, Barcode- und QR-Scanner, Sprachaufnahmen mit MediaRecorder und Audio-Analyse mit der Web Audio API. Den Stream zeigt man meist an, indem man ihn der Eigenschaft srcObject eines <video>-Elements zuweist.
Wichtig: Die API gibt es nur in einem sicheren Kontext (HTTPS oder localhost). Nach der Nutzung sollte man alle Spuren mit track.stop() beenden. Erst dann geht die Aufnahme-Anzeige (etwa die Kamera-LED) aus und das Gerät ist wieder frei.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $constraints Pflicht | MediaStreamConstraints | Objekt mit den Schlüsseln audio und/oder video. Jeder Wert ist entweder boolean oder ein MediaTrackConstraints-Objekt, z. B. { width: { ideal: 1280 }, facingMode: 'user' }. Mindestens einer der beiden Schlüssel muss angefordert werden, sonst wird ein TypeError geworfen. |
Rückgabewert
MediaStream erfüllt wird, sobald der Benutzer zustimmt. Es wird mit einer DOMException abgelehnt, u. a. mit folgenden Namen: NotAllowedError (Zugriff verweigert oder unsicherer Kontext), NotFoundError (kein passendes Gerät), NotReadableError (Gerät belegt oder Hardwarefehler), OverconstrainedError (exact/min-Vorgaben nicht erfüllbar; die Eigenschaft constraint nennt die betroffene Vorgabe), AbortError und SecurityError. Bei ungültigen Constraints wird mit einem TypeError abgelehnt.Beispiele
Kamerabild in einem video-Element anzeigen
// HTML: <video id="preview" autoplay playsinline muted></video>
const video = document.querySelector('#preview');
const startCamera = async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: { width: { ideal: 1280 }, height: { ideal: 720 } },
audio: false
});
video.srcObject = stream;
const [track] = stream.getVideoTracks();
console.log('Kamera aktiv:', track.label, track.getSettings());
} catch (err) {
console.error(`${err.name}: ${err.message}`);
}
};
startCamera();
Fehler gezielt behandeln und Rückkamera bevorzugen
const getRearCamera = async () => {
try {
return await navigator.mediaDevices.getUserMedia({
video: { facingMode: { ideal: 'environment' } }
});
} catch (err) {
switch (err.name) {
case 'NotAllowedError':
alert('Bitte erlaube den Kamerazugriff in den Browser-Einstellungen.');
break;
case 'NotFoundError':
alert('Es wurde keine Kamera gefunden.');
break;
case 'NotReadableError':
alert('Die Kamera wird bereits von einer anderen Anwendung verwendet.');
break;
case 'OverconstrainedError':
console.warn('Vorgabe nicht erfüllbar:', err.constraint);
break;
default:
console.error(err);
}
return null;
}
};
const stream = await getRearCamera();
console.log(stream ? 'Stream bereit' : 'Kein Stream');
Sprachnachricht aufnehmen und Mikrofon wieder freigeben
const recordAudio = async (durationMs = 3000) => {
const stream = await navigator.mediaDevices.getUserMedia({
audio: { echoCancellation: true, noiseSuppression: true }
});
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = (e) => chunks.push(e.data);
const stopped = new Promise((resolve) => (recorder.onstop = resolve));
recorder.start();
setTimeout(() => recorder.stop(), durationMs);
await stopped;
// Wichtig: alle Spuren beenden, damit das Mikrofon frei wird
stream.getTracks().forEach((track) => track.stop());
return new Blob(chunks, { type: recorder.mimeType });
};
const blob = await recordAudio();
console.log(`Aufnahme: ${blob.size} Bytes, ${blob.type}`);
Ein bestimmtes Gerät per deviceId auswählen
// Gerätenamen (label) gibt es erst nach einer erteilten Berechtigung
const devices = await navigator.mediaDevices.enumerateDevices();
const mics = devices.filter((d) => d.kind === 'audioinput');
console.log(mics.map((m) => m.label));
const stream = await navigator.mediaDevices.getUserMedia({
audio: { deviceId: { exact: mics[0].deviceId } }
});
console.log('Verwendet:', stream.getAudioTracks()[0].label);
// Wichtig · Fallstricke
- Nur in sicheren Kontexten: Auf reinen HTTP-Seiten (außer
localhost) istnavigator.mediaDevicesundefined. Prüfe das vor dem Aufruf, etwa mitif (!navigator.mediaDevices?.getUserMedia). - iframes: Eingebettete Inhalte brauchen die Freigabe über die Berechtigungsrichtlinie, z. B.
<iframe allow="camera; microphone">. Sonst wird mitNotAllowedErrorabgelehnt. - Das Promise wird eventuell nie erledigt: Schließt der Benutzer den Berechtigungsdialog nicht, bleibt das Promise offen. Die Oberfläche sollte darauf nicht blockierend warten.
- Spuren beenden: Ohne
track.stop()bleiben Kamera bzw. Mikrofon aktiv, auch wenn das<video>-Element entfernt wurde. Das ist ein Datenschutzproblem. exactsparsam verwenden:exact- undmin-Vorgaben führen schnell zuOverconstrainedError. Mitidealsucht der Browser die beste verfügbare Näherung.- Autoplay auf iOS/Safari: Das
<video>-Element brauchtplaysinlineund meistmuted. Sonst wird der Stream nicht inline abgespielt. - Veraltete API:
navigator.getUserMedia()und Varianten mit Präfix wiewebkitGetUserMediasind veraltet und arbeiten mit Callbacks. Verwende ausschließlichnavigator.mediaDevices.getUserMedia(). - Bildschirmfreigabe läuft nicht über diese Methode, sondern über
getDisplayMedia().