Hendry Lim
Hendry Lim

Reputation: 1974

Stop Webcam in React Component in ComponentWillUnmount

I have a react component that starts a webcam when a component called VideoPage is mounted.

However, when I navigate to another page, the webcam is still running in the background. I know this because the webcam activity light is still activated on my laptop.

I believe I will to 'kill' the webcam in the React lifecycle method ComponentWillUnmount when the component unmounts. How can I achieve that?

My code is below. I appreciate the advice. 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>
    );
  }
}

Upvotes: 4

Views: 5168

Answers (2)

Hendry Lim
Hendry Lim

Reputation: 1974

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

Here's a link to a github repo with my solution... 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");
  };

Upvotes: 0

Kaiido
Kaiido

Reputation: 136658

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());

Upvotes: 5

Related Questions