MediaStream API — der pragmatische Standard
Die MediaStream API (Teil der WebRTC-Familie) ist seit 2015 in allen Mainstream-Browsern verfügbar. Mit ihr greift eine Webseite — nach expliziter Erlaubnis — auf Webcam, Smartphone-Kamera und Mikrofon zu. 2026 hat sich der Stack stabilisiert und ist Mainstream-tauglich für Profilfoto-Upload, QR-Scan, Live-Filter, AR-Effekte und Document-Scan.
Das Grund-Pattern
async function startCamera() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: {
facingMode: "user", // "environment" für Rückkamera
width: { ideal: 1920 },
height: { ideal: 1080 }
},
audio: false
});
const video = document.querySelector("video");
video.srcObject = stream;
await video.play();
} catch (err) {
console.error("Camera access denied or unavailable:", err);
}
}Berechtigungen und UX
getUserMedia() löst eine Browser-Permissions-Dialog aus. Wichtige UX-Praktiken:
- Niemals beim Page-Load fragen. Erst nach einer expliziten Nutzer- Aktion (Button-Klick) — sonst lehnen Nutzer pauschal ab.
- Vorab erklären, warum. Ein kurzer Hinweis „Wir nutzen die Kamera für dein Profilfoto" vor der Browser-Frage erhöht die Zustimmung-Rate messbar.
- Fallback anbieten. Wenn Berechtigung verweigert wird, klassischen File-Upload als Plan B.
- Berechtigung gespeichert. Chrome merkt sich die Antwort per Site — beim zweiten Besuch wird kein Dialog mehr gezeigt.
Snapshot im Canvas erstellen
Aus einem laufenden Video-Stream einen statischen Schnappschuss machen:
function takeSnapshot(video) {
const canvas = document.createElement("canvas");
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const ctx = canvas.getContext("2d");
ctx.drawImage(video, 0, 0);
return canvas.toBlob(blob => {
const url = URL.createObjectURL(blob);
document.querySelector("img.preview").src = url;
}, "image/jpeg", 0.9);
}Das Blob kann direkt als Profilfoto hochgeladen, in IndexedDB gespeichert oder weiter verarbeitet werden — z.B. mit Background-Removal.
Use-Case 1 — Profilfoto-Upload
Der Klassiker: Nutzer macht ein Selfie für sein Profil. Best Practice:
- Kamera mit
facingMode: "user"für Selfie-Cam. - Live-Preview mit weicher Crop-Box im Overlay (z.B. Kreis 400×400).
- Spiegelung der Vorschau (CSS
transform: scaleX(-1)) — Nutzer sieht sich wie im Spiegel. - Beim Capture: nicht gespiegelt speichern.
- Auf dem Server EXIF strippen (siehe EXIF-Beitrag).
Use-Case 2 — QR-Code-Scan
Browser-QR-Scan ohne native App. Stack: getUserMedia() + Canvas + die zxing-wasm-Library (WebAssembly-Port von ZXing). Performance auf Mid-Range-Smartphones: 5–10 FPS, ausreichend für stabilen Scan.
Wichtig: Rückkamera nutzen via facingMode: "environment". Auf Smartphones ist die Auto-Fokus-Funktion entscheidend — über applyConstraints({ focusMode: "continuous" }) aktivieren.
Use-Case 3 — Document-Scan
Pass-Foto, Vertrag, Quittung digitalisieren. Pipeline:
- Kamera-Stream im Vollbild.
- Edge-Detection per OpenCV.js oder neuerem
shape-detector-api(Chrome). - Auto-Crop auf den erkannten Dokument-Umriss.
- Perspektivische Korrektur (Trapez → Rechteck).
- Schwarzweiß-Konvertierung mit adaptiver Threshold-Erkennung.
- Export als PNG oder PDF.
Browser-only-Document-Scanner sind 2026 wettbewerbsfähig mit nativen Apps wie Scanner Pro oder Adobe Scan — mit der Datenschutz-Stärke, dass nichts hochgeladen wird.
Use-Case 4 — AR-Vorschau
Möbel-Käufer wollen sehen, wie der Stuhl in der eigenen Wohnung aussieht. Browser-AR ist 2026 produktiv möglich via:
- WebXR Device API: native AR-Sessions in Chrome auf Android- ARCore-Geräten und Safari auf iPhones (seit visionOS 1.0).
- MediaStream + Three.js/AR.js: poor-man's AR via Marker-Tracking, funktioniert in jedem Browser.
- Model-Viewer Web Componentvon Google: einbettet ein 3D-Modell mit einem "In AR ansehen"-Button, der iOS-Quick-Look oder Android-Scene-Viewer startet.
Use-Case 5 — Live-Hintergrund-Effekte
Video-Stream live verarbeiten: Hintergrund-Blur (wie Zoom), Greenscreen-Ersatz, Beauty-Filter. Stack:
getUserMedia()Stream.- Frame-by-Frame via
requestVideoFrameCallback. - Segmentation mit MediaPipe oder BiRefNet (siehe Background-Removal-Beitrag).
- Composit mit dem Ersatz-Hintergrund auf einem zweiten Canvas.
- Output-Stream via
captureStream()in ein neues Video-Element.
Performance: auf einer M2-CPU mit WebGPU 30+ FPS bei 720p. Auf Mid-Range-Android mit MediaPipe ~15–20 FPS — akzeptabel.
Browser-Kompatibilität 2026
- Chrome 110+: volles MediaStream-API plus WebGPU-Accelerated-Processing.
- Safari 17+: stabil auf macOS und iOS. iOS 17 brachte endlich PWA-Camera-Access ohne Safari-Detour.
- Firefox 130+: volles MediaStream, WebGPU seit 2025 stabil.
- Edge: Chromium-basiert, identisch zu Chrome.
- Mobile In-App-Browser (TikTok, Instagram): oft eingeschränkt. Wenn Nutzer aus einer App heraus deinen Link öffnet, kann Kamera-Access fehlen.
Datenschutz-Praxis
- Stream immer beenden, wenn die Funktion fertig ist:
stream.getTracks().forEach(t => t.stop()). Sonst läuft die Kamera weiter und die LED bleibt an. - Nie unerwartet aufzeichnen. Die
MediaRecorder-API kann Audio/Video aufzeichnen. Wer das nutzt, sollte explizit zustimmen lassen. - HTTPS-Pflicht.
getUserMedia()funktioniert nur über HTTPS oder auflocalhost. Sicher gegen MITM-Lauscher.
HTML-Fallback ohne MediaStream
Auf Mobile gibt es einen schönen klassischen Weg: <input type="file" accept="image/*" capture="user"> öffnet auf iOS und Android direkt die Kamera-App. Kein Permission-Dialog, kein Stream-Management. Nicht so flexibel wie MediaStream, aber für „mach ein Foto und lade es hoch"-Use-Cases oft die einfachere Wahl.
Tools-Empfehlung
- Web-API direkt: für einfache Foto-Capture und Profilfoto-Upload.
- html5-qrcode oder zxing-wasm: für QR-Scan.
- MediaPipe: für Face-Detection, Segmentation, Pose-Estimation.
- OpenCV.js: für klassische Bildverarbeitungs-Algorithmen.
- Google's model-viewer: für AR-Vorschau ohne eigenen 3D-Stack.
Quellen
MDN — getUserMedia · W3C — Media Capture and Streams · Google MediaPipe · zxing-js library · OpenCV.js · W3C — WebXR Device API · model-viewer (Google) · web.dev — Capturing Images.