Signatur
Beschreibung
takePhoto() löst über die Kamera, die an einem Video-MediaStreamTrack hängt, eine echte Einzelaufnahme aus. Im Gegensatz zu grabFrame(), das nur ein Einzelbild aus dem laufenden Videostrom kopiert, nutzt takePhoto() die eigentliche Fotofunktion des Geräts. Deshalb sind oft höhere Auflösungen möglich, und Blitz oder Rote-Augen-Reduzierung lassen sich einsetzen.
Das zurückgegebene Promise wird mit einem Blob erfüllt, meist im Format image/jpeg. Diesen Blob kannst du direkt hochladen, mit URL.createObjectURL() in einem <img> anzeigen oder mit createImageBitmap() weiterverarbeiten.
Über das optionale Objekt photoSettings kannst du Auflösung, Blitz und Rote-Augen-Reduzierung für diese eine Aufnahme festlegen. Welche Werte erlaubt sind, liefert vorher getPhotoCapabilities(). Die aktuell eingestellten Werte liefert getPhotoSettings().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $photoSettings | object | {} | Optionale Einstellungen für die Aufnahme: fillLightMode ("auto", "off" oder "flash"), imageHeight und imageWidth (Zahl, in Pixeln) sowie redEyeReduction (boolean). |
Rückgabewert
Promise, das mit einem Blob mit den Bilddaten erfüllt wird. Es wird mit einer DOMException abgelehnt, zum Beispiel mit InvalidStateError, wenn der Track beendet oder stummgeschaltet ist, oder mit UnknownError, wenn die Aufnahme fehlschlägt.Beispiele
Einfaches Foto aufnehmen und anzeigen
const aufnehmen = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const capture = new ImageCapture(track);
try {
const blob = await capture.takePhoto();
const img = document.querySelector('#vorschau');
img.src = URL.createObjectURL(blob);
console.log(`Foto: ${blob.type}, ${blob.size} Bytes`);
} finally {
track.stop(); // Kamera wieder freigeben
}
};
document.querySelector('#ausloeser').addEventListener('click', aufnehmen);
Maximale Auflösung und Blitz anhand der Fähigkeiten wählen
const fotoInHoherQualitaet = async (track) => {
const capture = new ImageCapture(track);
const caps = await capture.getPhotoCapabilities();
const settings = {
imageWidth: caps.imageWidth.max,
imageHeight: caps.imageHeight.max,
};
if (caps.fillLightMode.includes('flash')) {
settings.fillLightMode = 'flash';
}
if (caps.redEyeReduction === 'controllable') {
settings.redEyeReduction = true;
}
return capture.takePhoto(settings);
};
const stream = await navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment' },
});
const blob = await fotoInHoherQualitaet(stream.getVideoTracks()[0]);
console.log(blob.size);
Foto mit Feature-Erkennung hochladen
const fotoHochladen = async (track) => {
if (!('ImageCapture' in window)) {
throw new Error('ImageCapture wird nicht unterstützt');
}
const blob = await new ImageCapture(track).takePhoto();
const form = new FormData();
form.append('foto', blob, 'aufnahme.jpg');
const res = await fetch('/api/upload', { method: 'POST', body: form });
console.log(res.ok ? 'Hochgeladen' : `Fehler ${res.status}`);
};
// Wichtig · Fallstricke
- Browser-Unterstützung: Nur Chromium-basierte Browser (Chrome, Edge, Opera, Samsung Internet) unterstützen die Methode. Firefox und Safari bieten
ImageCapturenicht an. Prüfe die Verfügbarkeit mit'ImageCapture' in windowund greif sonst auf<canvas>mitdrawImage(video)zurück. - Sicherer Kontext und Berechtigung: Die Methode braucht HTTPS (oder
localhost) und die Kamerafreigabe durch die Nutzerin oder den Nutzer übergetUserMedia(). - Track-Zustand: Ist der Track beendet (
readyState === 'ended') oder stummgeschaltet, wird das Promise mitInvalidStateErrorabgelehnt. - Stream kann kurz stocken: Auf manchen Geräten schaltet die Kamera für die Aufnahme um. Die Videovorschau kann dann kurz einfrieren oder ihre Auflösung ändern. Wenn du Einzelbilder schnell hintereinander brauchst, ist
grabFrame()besser geeignet. - Werte der Einstellungen: Werte außerhalb der Bereiche aus
getPhotoCapabilities()können zu einer Ablehnung führen oder stillschweigend angepasst werden. Lies die erlaubten Werte deshalb vorher aus. - Speicher: Gib Objekt-URLs nach der Anzeige mit
URL.revokeObjectURL()wieder frei.