javascript camera
First written: Jul-2023
last changed Jan-2024

Collecting a static image from a browser has a number of hurdles and problems involved, but amazingly - the easiest option actually comes from using the basic html input tag:

html
<input type='file' accept='image/*' capture='camera'>

    info it is important to note that this works with mobile devices but not desktop; a mobile device will present the devices camera, showing the image to be taken, and giving you all the other basic camera options (zoom, switch view, etc) - but not necessarily page edge detection.

    Using the same html (<input type='file'>) tag on a desktop environment will result in a prompt for a file from the filesystem.

This will then use the camera resolution to capture images. This is the main difference from trying to achieve the same result using navigator.mediaDevices.getUserMedia in javascript which will use the video camera and its [typically] lower resolution.

Javascript implementation to collect images from the video camera

To implement an image capture via javascript then you can use this option too, but beware it will use the device video camera and its resolution.

It should be noted that IOS seems to behave differently from Android, in that the camera selector works with "facingMode" = "user" or "environment" on an iPad, but on an android (with more than 2 cameras) then you can use "deviceId"

js :: startCamera function
    async function startCamera() {
    let constraints;
    let devices, videoDevices,selectedDevice;
    if (isIOS()) {
        if ( selectedCameraId!='' ) {
            constraints = {
                audio: false,
                video: {
                    facingMode: selectedCameraId
                    , frameRate: {ideal: 5, max: 30}
                }
            }
        }
    }
    else {
        devices        = await navigator.mediaDevices.enumerateDevices();
        videoDevices   = devices.filter(device => device.kind === 'videoinput');
        selectedDevice = videoDevices.find(device => device.deviceId === selectedCameraId);
    
    
        if (selectedDevice) {
            constraints = {
                video: {
                    deviceId   : selectedCameraId
                    , frameRate: {ideal: 5, max: 30} // Set your desired frame rate here (in this example, 15 fps); lower rates will reduce the demand on the device - which will heat up if left on too long
                },
                audio: false
            };
        }
    }
    
    
    if ( constraints ) {
        await navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
            _mediaStream = stream;
            _videoElement.srcObject = stream;
    
            _videoElement.setAttribute('autoplay', '');
            _videoElement.setAttribute('muted', '');
            _videoElement.setAttribute('playsinline', '');
        });
    }

js :: takeSnapshot function
function takeSnapshot() {
    const ctx = snapshotCanvas.getContext('2d');
    ctx.drawImage(videoElement, 0, 0, snapshotCanvas.width, snapshotCanvas.height);
    snapshotImage.src = snapshotCanvas.toDataURL('image/'+imgtype.value);
}


link Click to view a demo

square