Stop Webcam in React Component in ComponentWillUnmount

Viewed 3235

I have a react component which starts a webcam when the component VideoPage is mounted

However, when I go to another page, the webcam is still running in the background cause my laptop's webcam lights is still on

I believe I will need to 'kill' the webcam in React lifecycle method ComponentWillUnmount when exiting the component. How am I able to do that?

Below are my codes... Appreciate advise. Thanks

import React from "react";

export default class VideoPage extends React.Component {
  constructor(props) {
    super(props);

    this.videoTag = React.createRef();

    this.state = {
      loading: false
    };
  }

  componentDidMount() {
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then(this.handleStream)
      .catch(err => console.log(err));
  }

  handleStream = async stream => {
    // start receiving stream from webcam
    this.videoTag.current.srcObject = stream;

    console.log("The video is ready");
  };

  render() {
    return (
      <div>
        <div style={{ paddingTop: 20 }}>
          <video
            id="myvideo"
            ref={this.videoTag}
            width={426}
            height={240}
            autoPlay
            title="video"
          />
        </div>
      </div>
    );
  }
}
2 Answers

To stop a getUserMedia request, you need to call the stop() method of the MediaStreamTracks it generated.
To access these MediaStreamTracks, you need to call the getTracks() method of the stream MediaStream you received in your handleStream method.

So it would be good to save your stream somewhere in your instance, e.g as this.stream.
Then in your componentWillUnmount, you will call

this.stream.getTracks()
  .forEach((track) => track.stop());

Thanks to @Kalido answer, my final working code is as below...

the complete codes can be found here... Github Repo

  constructor(props) {
    // set up constructor
    super(props);

    // create video ref
    this.videoTag = React.createRef();
    this.myStream = null;

    // set up initial state
    this.state = {
      guess: "",
      probability: null,
      loading: false,
      scale: defaultValue
    };
  }

  componentDidMount() {
    // set up webcam when component mounting
    navigator.mediaDevices
      .getUserMedia({ video: true })
      .then(this.handleStream)
      .catch(err => console.log(err));
  }

  componentWillUnmount() {
    this.myStream.getTracks().forEach(track => track.stop());
  }

  handleStream = async stream => {
    this.myStream = stream;

    // start receiving stream from webcam
    this.videoTag.current.srcObject = stream;

    // prepare classifier and assign myClassifier in global scope
    myClassifier = await this.prepareClassifier(this.videoTag.current);
    console.log(myClassifier);
    console.log("The video is ready");
  };
Related