LWC: How to Access Your Device Camera

LWC: How to Access Your Device Camera

ยท

4 min read

Hey there! Today, we're going to have some fun learning how to access your device's camera and snap pictures using the LWC component. Let's get started!

We've all experienced the challenges posed by Locker Service and the various web APIs it used to block. Thankfully, Salesforce has heard our concerns. Introducing Lightning Web Security to the rescue.

What is Lightning Web Security?

Introducing Lightning Web Security (LWS), the hip younger sibling of Lightning Locker! It's the fresh new face of client-side security for Lightning Web Components (LWC). LWS is like that cool uncle who lets you have a bit more freedom but still keeps you safe from the bad guys. With fewer restrictions and the same muscle to keep those pesky, insecure APIs in check, LWS is ready to step into the ring and champion the cause of secure LWCs! ๐ŸฅŠ๐Ÿ’ฅ
You can read more on LWS here.

Alright, time for the fun part - let's dive into the code! ๐Ÿ˜„

Here we will see how to access the device's camera (mobile/browser) using Javascript native api navigator and capture images.

Enable Lighting Web Security from Session Settings.

Create an LWC component named "cameraCapture".

    <template>
        <div class="camera-wrapper">
            <lightning-button label="Start Video" class="slds-m-left_xx-small" onclick={initCamera}></lightning-button>
            <lightning-button label="Stop Video" class="slds-m-left_xx-small" onclick={stopCamera}></lightning-button>
            <lightning-button label="Capture Image" class="slds-m-left_xx-small" onclick={captureImage}></lightning-button>
        </div>
        <div class="slds-grid slds-gutters">
            <div class="slds-col">
                <video class="videoElement" autoplay></video>
                <canvas class="slds-hide canvas"></canvas>
            </div>
            <div class="slds-col">
                <img src="" class="slds-hide imageElement" alt="captured image"/>
            </div>
        </div>
    </template>
import {LightningElement} from 'lwc';

export default class CameraCapture extends LightningElement {
    videoElement;
    canvasElement;


    renderedCallback() {
        this.videoElement = this.template.querySelector('.videoElement');
        this.canvasElement = this.template.querySelector('.canvas');
    }


    async initCamera() {
        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
            try {
                this.videoElement.srcObject = await navigator.mediaDevices.getUserMedia({video: true, audio: false});
            } catch (error) {
                console.error('Error accessing the camera: ', JSON.stringify(error));
            }
        } else {
            console.error('getUserMedia is not supported in this browser');
        }
    }

    async captureImage() {
        if(this.videoElement && this.videoElement.srcObject !== null) {
            this.canvasElement.height = this.videoElement.videoHeight;
            this.canvasElement.width = this.videoElement.videoWidth;
            const context = this.canvasElement.getContext('2d');
            context.drawImage(this.videoElement, 0, 0, this.canvasElement.width, this.canvasElement.height);
            const imageData = this.canvasElement.toDataURL('image/png');
            const imageElement = this.template.querySelector('.imageElement');
            imageElement.setAttribute('src', imageData);
            imageElement.classList.add('slds-show');
            imageElement.classList.remove('slds-hide');
        }
    }

    async stopCamera(){
        const video = this.template.querySelector(".videoElement");
        video.srcObject.getTracks().forEach((track) => track.stop());
        video.srcObject = null;
        this.hideImageElement();
    }

    hideImageElement(){
        const imageElement = this.template.querySelector('.imageElement');
        imageElement.setAttribute('src', "");
        imageElement.classList.add('slds-hide');
        imageElement.classList.remove('slds-show');
    }
}

Method explanation :

  1. initCamera: The mediaDevices property is utilized to gain access to connected media input devices, such as cameras and microphones, as well as screen sharing. The getUserMedia() method prompts the user for permission to use a media input, which in turn produces a MediaStream with tracks containing the requested types of media. Ultimately, the media stream is inserted into the Video element.

  2. stopCamera: When you invoke the stop() method, it signals to the user agent that the source of the MediaStreamTrack, which could be files, network streams, or local devices like a camera or microphone, is no longer required.

  3. captureImage: This method captures a frame from a video element and draws it onto a canvas element. It then converts the canvas content into a PNG image and sets the src attribute of an image element to display the captured frame.

NOTE: Just a quick note for you: LWS is exclusively available for LWC, so it'll only work on communities built on LWR and not on Aura (still in beta). But don't worry, it'll also work perfectly on your Salesforce Lightning pages. Happy coding!

Demo

Let's see a small demo.

So, what's coming up next? In my following blog post, I'll be guiding you through using this awesome technique to analyze documents with Amazon Textract OCR. Can't wait to share it with you, so stay tuned! ๐Ÿ˜Š

This article provides instructions on how to use the Lightning Web Component (LWC) to access a device's camera and take pictures, including enabling Lightning Web Security (LWS) and code snippets. It also explains how to use the mediaDevices property and getUserMedia() method to produce a MediaStream, and how to capture a frame from a video element and draw it onto a canvas element. The author will be discussing how to use this technique to analyze documents with Amazon Textract OCR in their next blog post.

Did you find this article valuable?

Support Nagendra Singh by becoming a sponsor. Any amount is appreciated!

ย