getUserMedia and Image Capture

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.

Opening the camera and taking a photoJavaScript
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.