navigator.mediaDevices.getUserMedia(constraints) asks for a camera and/or microphone and resolves to a MediaStream. Constraints such as width, frameRate, deviceId (from enumerateDevices()) or facingMode: 'environment' (the rear camera) take plain values or ideal, min, max and exact; a refusal rejects with NotAllowedError. The Image Capture API then takes stills from the video track.
const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: { width: 1280 } });
video.srcObject = stream; // <video autoplay muted playsinline>
const [track] = stream.getVideoTracks();
const { width, height, frameRate } = track.getSettings(); // what you actually got
console.log(`${track.label}: ${width}x${height} @ ${frameRate} fps`);
const photo = await new ImageCapture(track).takePhoto(); // grabFrame() returns an ImageBitmap
console.log(`photo: ${photo.type}, ${photo.size} bytes`);Output
fake_device_0: 1280x720 @ 20 fps photo: image/png, 5617 bytes
Without ImageCapture (Firefox 555 ), draw the video onto a canvas. Call track.stop() when done, or the camera light stays on.