"Client-side Webcam Integration in React: A Comprehensive Guide

Abdul RehmanAbdul Rehman
5 min read

Real-time video streams from client-side webcams can bring your React applications to life. In this comprehensive guide, I'll show you how to integrate client-side webcams into your React applications. We'll go over everything in detail, from setting up the webcam stream to using the video in your React components. Whether you're a beginner or an experienced React developer, this guide will take you from scratch to building amazing webcam-powered applications in no time!

Motivation

The motivation behind this webcam integration is that, I was shifting my primary programming language from Python to JavaScript. So was looking a complete alternative to it. So I wanted to try If I can use the Image Processing in web applications as well or not? Surprisingly I came to know that there are complete solution pack for this which includes

  • Tensorflow.js

  • OpenCV.js

  • React.js

Last but not least, we have option to create the python based flask or django backend as well. So I think to give it a try and In this tutorial series I would be trying and will keep sharing the code with you. I will try my best to keep updated in this hashnode blog post series.

First Step is to create a canvas

The resultant Image frame would be displayed onto the canvas object from the HTML element. So let's create a simple HTML based interface for our application

<div style="display:'grid'">
    <h1>Simple Webcam with React </h1>
      <button >Start Webcam</button>
      <button >Stop Webcam</button>
      <canvas width="640" height="480" />
</div>

In above code as you can see this is simple HTML element with the name canvas and we described width and height of it. For the parent dive we simply style it to be a grid so that all the buttons are lined up vertically. Two buttons are required to start the webcam feed and to stop the webcam feed. We are not going to create a fancy frontend for this so let's keep this simple. Now we can shift to our react application and create our Webcam component.

Client Side Webcam Access in React

Let's create a react component and use the above HTML in that function level component.

import React, { useState, useRef } from 'react';

export function ClientWebCam(){
     const canvasRef = useRef(null);

    function handleStartWebcam(){

    }

    function handleStopWebcam(){

    }

   <div style={{display:'grid'}}>
    <h1>Simple Webcam with React </h1>
      <button onClick={handleStartWebcam}>Start Webcam</button>
      <button onClick={handleStopWebcam}>Stop Webcam</button>
      <canvas ref={canvasRef} width={640} height={480} />
    </div>
}

In the above code we give reference of canvas using useRef and created two functions to handle the Start Webcam as well as Stop Webcam functionality.

Create a Webcam Stream

Now let's create a webcam stream which is pretty simple. First of all let's create a simple hook to set the stream variable to hold the local state of either the stream is running or stopped. This could be accomplished by simply

const [stream, setStream] = useState(null);

After that we can change our start stream and stop stream event handlers to set this variable accordingly

const handleStartWebcam = async () => {
      const mediaStream = 'something'//this need to be changed later
    setStream(mediaStream);
  };

  const handleStopWebcam = () => {
    setStream(null);
  };

Now we are able to keep track of start and stopped state of the stream.

Creating Webcam stream

Now let's come to the main part where we are going to create the actual streaming. A simple webcam stream from the client side is simple plain javascript like following

  const mediaStream = await navigator.mediaDevices.getUserMedia({
      video: true
    });

As you may guess we need to change our event handler to async so that this asynchronous code could work properly

 const handleStartWebcam = async () => {
    const mediaStream = await navigator.mediaDevices.getUserMedia({
      video: true
    });
    setStream(mediaStream);
  };

and to stop these streams we need to loop over all previously running states and stop them.

  const handleStopWebcam = () => {
    const tracks = stream.getTracks();
    tracks.forEach(track => track.stop());
    setStream(null);
  };

UseEffect Hook to render Stream

Now that we are done with handling our stream object, we somehow need to create this stream rendering and we can use the React.useEffect() hook for this. We need to pass this stream object to that hook so that it could easy change the rendering accordingly. Here is how we do this

  React.useEffect(() => {
    if (!stream) {
      return;
    }

    const canvas = canvasRef.current;
    const context = canvas.getContext('2d');
    const video = document.createElement('video');
    video.srcObject = stream;
    video.play();

    const render = () => {
      context.drawImage(video, 0, 0, canvas.width, canvas.height);
      requestAnimationFrame(render);
    };

    requestAnimationFrame(render);

    return () => {
      const tracks = stream.getTracks();
      tracks.forEach(track => track.stop());
    };
  }, [stream]);

Final Code in React

Now that we are done with everything we are ready to assemble each piece to make a complete ClientWebCam Componenet. Here is the final code for this

import React, { useState, useRef } from 'react';

const ClientWebCam= () => {
  const [stream, setStream] = useState(null);
  const canvasRef = useRef(null);

  const handleStartWebcam = async () => {
    const mediaStream = await navigator.mediaDevices.getUserMedia({
      video: true
    });
    setStream(mediaStream);
  };

  const handleStopWebcam = () => {
    const tracks = stream.getTracks();
    tracks.forEach(track => track.stop());
    setStream(null);
  };

  React.useEffect(() => {
    if (!stream) {
      return;
    }

    const canvas = canvasRef.current;
    const context = canvas.getContext('2d');
    const video = document.createElement('video');
    video.srcObject = stream;
    video.play();

    const render = () => {
      context.drawImage(video, 0, 0, canvas.width, canvas.height);
      requestAnimationFrame(render);
    };

    requestAnimationFrame(render);

    return () => {
      const tracks = stream.getTracks();
      tracks.forEach(track => track.stop());
    };
  }, [stream]);

  return (
    <div style={{display:'grid'}}>
    <h1>Simple Webcam with React </h1>
      <button onClick={handleStartWebcam}>Start Webcam</button>
      <button onClick={handleStopWebcam}>Stop Webcam</button>
      <canvas ref={canvasRef} width={640} height={480} />
    </div>
  );
};

export default ClientWebCam;

and we can use this component in our App.jsx component like this

import React from 'react';
import ClientWebCamfrom './ClientWebCam'
export function App ()  {

  return (
    <div>
      <ClientWebCam/>
    </div>
  );
};
0
Subscribe to my newsletter

Read articles from Abdul Rehman directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abdul Rehman
Abdul Rehman