Languages
[Edit]
EN

React - play web camera on video element (custom WebCamera component)

3 points
Created by:
Anisha-Kidd
652

In this short article, you can see how in React create custom web camera component using video element and stream video to it.

Example preview:

Example camera streaming to video element using React
Example camera streaming to video element using React

Practical example

In this example, we present how to create reusable WebCamera component to which we can pass the following properties:

  • width - WebCamera component width in px (equals to video width),
  • height - WebCamera component height in px (equals to video height),
  • onReady - function to be executed once the WebCamera component is ready,
  • onError - function to be executed when some error occurs.

Note:

It is important to be sure the web camera is connected properly, permissions for camera are granted and it is not used by any other application.

// ONLINE-RUNNER:browser;

// import React from 'react';

// -- camera utils -----------------------------

const playStream = (video, stream, callback) => {
    const handleLoaded = () => {
        video.removeEventListener('loadedmetadata', handleLoaded);
        video.play();
        if (callback) {
            callback(stream);
        }
    };
    video.addEventListener('loadedmetadata', handleLoaded);
    video.srcObject = stream;
};

const stopStream = (stream) => {
    for (const track of stream.getTracks()) {
        track.stop();
    }
};

const playCamera = (video, preferedWidth, preferedHeight, onReady = null, onError = null, audioConstraints = null, videoConstraints = null) => {
    let _stream = null;
    let _destroyed = false;
    const constraints = {
        video: {
            width: preferedWidth,
            height: preferedHeight,
            ...videoConstraints
        },
        audio: audioConstraints
    };
    const promise = navigator.mediaDevices?.getUserMedia?.(constraints);
    if (promise) {
        promise
            .then((stream) => {
                if (_destroyed) {
                    stopStream(stream);
                } else {
                    _stream = stream;
                    playStream(video, stream, onReady);
                }
            })
            .catch((error) => {
                if (onError) {
                    onError(`${error.name}: ${error.message}`);
                }
            });
    } else {
        if (onError) {
            onError('Camera API is not supported.');
        }
    }
    return () => {
        if (_destroyed) {
            return;
        }
        if (_stream) {
            stopStream(_stream);
            _stream = null;
        }
        _destroyed = true;
    };
};

// -- react hooks ------------------------------

// Wraps action function with function that doesn't change its reference.
// It is useful when we want to pass a function to component as prop preventing unnecessary re-rendering on reference change.
//
const useProxy = (action) => {
    const state = React.useMemo(
        () => ({
            wrapper: (...args) => {
                if (state.action) {
                    return state.action(...args);
                }
                return undefined;
            },
        }),
        []
    );
    state.action = action;
    return state.wrapper;
};

// -- react components -------------------------

const WebCamera = ({ width, height, audioConstraints, videoConstraints, onReady, onError }) => {
    const ref = React.useRef();
    const handleReady = useProxy(onReady); // by using proxy, onReady is wrapped in function which reference doesn't change
    const handleError = useProxy(onError); // by using proxy, onError is wrapped in function which reference doesn't change
    React.useEffect(
        () => playCamera(ref.current, width, height, handleReady, handleError, audioConstraints, videoConstraints),
        [width, height] // by using useProxy, we don't need to track onReady and onError functions
    );
    return <video ref={ref} width={width} height={height} />;
};



// Usage example:

const App = () => {
    const handleReady = (stream) => {
        console.log('Web camera is ready and working');
    };
    const handleError = (error) => {
        console.error(error);
    };
    return (
        <div>
          <WebCamera width={640} height={480} onReady={handleReady} onError={handleError} />
        </div>
    );
};

const root = document.querySelector('#root');
ReactDOM.render(<App />, root);

 

It is possible to configure audio and video constraints manually by:

// https://developer.mozilla.org/en-US/docs/Web/API/Media_Capture_and_Streams_API/Constraints
  
                              // navigator.mediaDevices.getUserMedia({
const audioConstraints = {    //     audio: {
    sampleSize: 16,           //         sampleSize: 16,
    channelCount: 2           //         channelCount: 2
};                            //     },
const videoConstraints = {    //     video: {
    width: 1920,              //         width: 1920,
    height: 1080,             //         height: 1080
};                            //     }
                              // });
return (
    <WebCamera
        width={640}
        height={480}
        audioConstraints={audioConstraints}
        videoConstraints={videoConstraints}
        onReady={handleReady}
        onError={handleError}
    />
);

 

Giving premissions

When a web camera is accessed from React you should see notification to permit using it. Just let use it by desired website and remove permissions when it is not needed.

Giving permissions to use web camera under Google Chrome web browser.
Giving permissions to use web camera under Google Chrome web browser.

See also

  1. JavaScript - play web camera on video element

References

  1. MediaDevices - MDN Docs
  2. MediaDevices.getUserMedia() - MDN Docs

  3. HTMLMediaElement.srcObject - MDN Docs

  4. <video>: The Video Embed element - MDN Docs

Alternative titles

  1. React - stream web camera to video element
  2. React - web camera own components
  3. React - web camera custom components
  4. React - webcam own components
  5. React - webcam custom components
Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join