Signatur
Beschreibung
ImageCapture gehört zur MediaStream Image Capture API. Das Objekt wird mit einer Video-Spur (MediaStreamTrack mit kind === "video") erzeugt, die man meist über navigator.mediaDevices.getUserMedia() bekommt. Damit lassen sich echte Fotos in voller Sensorauflösung aufnehmen – oft deutlich höher als die Auflösung des laufenden Videostreams.
Wichtige Mitglieder:
new ImageCapture(videoTrack)– Konstruktor.track– schreibgeschützt; die übergebeneMediaStreamTrack.takePhoto(photoSettings?)– gibt einPromise<Blob>mit einem kodierten Foto zurück (z. B. JPEG). Optional könnenimageWidth,imageHeight,fillLightModeundredEyeReductionübergeben werden.grabFrame()– gibt einPromise<ImageBitmap>mit dem aktuellen Videoeinzelbild zurück. Das geht schnell, hat aber nur die Stream-Auflösung.getPhotoCapabilities()– gibt einPromise<PhotoCapabilities>zurück (unterstützte Bildgrößen, Blitz-Modi, Rote-Augen-Reduktion).getPhotoSettings()– gibt einPromise<PhotoSettings>mit den aktuellen Einstellungen zurück.
Die Schnittstelle eignet sich zum Beispiel für Dokumentenscanner, Profilfoto-Aufnahmen, Barcode-Vorverarbeitung oder Zeitraffer-Aufnahmen. Kamerafunktionen wie Zoom, Fokus oder Taschenlampe werden dagegen nicht über ImageCapture eingestellt, sondern über track.applyConstraints() und track.getCapabilities().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $videoTrack Pflicht | MediaStreamTrack | Konstruktor-Argument: eine Video-Spur, etwa aus stream.getVideoTracks()[0]. Ist kind nicht "video", wird ein NotSupportedError (DOMException) geworfen. |
|
| $photoSettings | { imageWidth?: number, imageHeight?: number, fillLightMode?: "auto"|"off"|"flash", redEyeReduction?: boolean } | {} | Optionales Argument für takePhoto(). Die Werte müssen innerhalb der Bereiche liegen, die getPhotoCapabilities() meldet. |
Rückgabewert
ImageCapture-Instanz, die fest an die übergebene Video-Spur gebunden ist.Beispiele
Instanz erzeugen und Foto als Blob aufnehmen
const takeSnapshot = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const [track] = stream.getVideoTracks();
const imageCapture = new ImageCapture(track);
const blob = await imageCapture.takePhoto();
console.log(`Foto: ${blob.type}, ${blob.size} Bytes`);
// Vorschau anzeigen
const img = document.querySelector('#photo');
img.src = URL.createObjectURL(blob);
img.onload = () => URL.revokeObjectURL(img.src);
track.stop(); // Kamera freigeben
};
document.querySelector('#shoot').addEventListener('click', takeSnapshot);
Einzelbild mit grabFrame() auf ein Canvas zeichnen
const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720 } });
const imageCapture = new ImageCapture(stream.getVideoTracks()[0]);
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const bitmap = await imageCapture.grabFrame();
canvas.width = bitmap.width;
canvas.height = bitmap.height;
ctx.drawImage(bitmap, 0, 0);
bitmap.close(); // Speicher sofort freigeben
console.log(`Frame: ${canvas.width}x${canvas.height}`);
Fähigkeiten abfragen und in maximaler Auflösung mit Blitz fotografieren
const stream = await navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } });
const imageCapture = new ImageCapture(stream.getVideoTracks()[0]);
const caps = await imageCapture.getPhotoCapabilities();
console.log('Breite:', caps.imageWidth.min, '–', caps.imageWidth.max);
console.log('Blitz-Modi:', caps.fillLightMode);
const settings = {
imageWidth: caps.imageWidth.max,
imageHeight: caps.imageHeight.max,
...(caps.fillLightMode.includes('flash') && { fillLightMode: 'flash' })
};
try {
const blob = await imageCapture.takePhoto(settings);
console.log('Aufgenommen:', blob.size, 'Bytes');
} catch (err) {
console.error('Aufnahme fehlgeschlagen:', err.name, err.message);
}
Feature-Erkennung mit Canvas-Fallback
const captureFrame = async (video) => {
const track = video.srcObject.getVideoTracks()[0];
if ('ImageCapture' in window) {
return new ImageCapture(track).grabFrame();
}
// Fallback für Firefox/Safari: aktuelles Videobild über ein Canvas holen
const canvas = new OffscreenCanvas(video.videoWidth, video.videoHeight);
canvas.getContext('2d').drawImage(video, 0, 0);
return createImageBitmap(canvas);
};
const video = document.querySelector('video');
video.srcObject = await navigator.mediaDevices.getUserMedia({ video: true });
await video.play();
const frame = await captureFrame(video);
console.log(frame.width, frame.height);
// Wichtig · Fallstricke
- Browser-Kompatibilität: Unterstützt wird die Schnittstelle nur in Chromium-Browsern (Chrome, Edge, Opera, Samsung Internet). Firefox und Safari kennen
ImageCapturenicht. Prüfe daher immer vorher mit'ImageCapture' in windowund sieh einen Canvas-Fallback vor. - Sicherer Kontext und Berechtigung:
getUserMedia()funktioniert nur über HTTPS oderlocalhostund nur mit Kamera-Freigabe durch die Nutzerin oder den Nutzer. In iframes ist außerdemallow="camera"nötig. - Beendete Spur: Wurde
track.stop()aufgerufen oder isttrack.readyStategleich"ended", werdentakePhoto()undgrabFrame()mitInvalidStateErrorabgelehnt. Eine stummgeschaltete oder deaktivierte Spur (enabled = false) führt ebenfalls zu Fehlern. - Parallele Aufrufe: Mehrere gleichzeitige
takePhoto()-Aufrufe können mitOperationErrorfehlschlagen. Warte deshalb jeden Aufruf perawaitab, bevor du den nächsten startest. - Nebenwirkungen: Unter Umständen stellt
takePhoto()die Kamera kurz um, sodass der Videostream stockt oder die Belichtung springt. Für schnelle Serienbilder istgrabFrame()besser geeignet. - Speicher:
ImageBitmap-Objekte mitclose()und Objekt-URLs mitURL.revokeObjectURL()freigeben. - Zoom, Fokus, Belichtung und Taschenlampe (
torch) werden überMediaStreamTrack.applyConstraints()gesteuert, nicht überphotoSettings.