How to handle React life cycle with http live streaming HLS?

1.9k views Asked by At

I'm using this hls.js player along with React to stream m3u8. I have one component VideoPlayer that sets up the hls.js player. This component has a couple of state properties, like isPlaying and isMuted. I have custom buttons that onClick call component functions to setState, but this of course re-renders the component and the video stream re-mounts I guess and is back to it's original state, which is back to it's first frame and stopped. In general, how do you deal with application (redux) or local state changes with streaming video? I notice the videos always have this "flicker" (which is it being re-rendered) any time the redux store updates, or local state changes.

UPDATE WITH CODE EXAMPLE:

import React, {PropTypes} from 'react';
import Hls from 'hls.js';

class VideoPlayer extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      isMuted: true,
      isPlaying: false,
      playerId : Date.now()
    };

    this.hls = null;
    this.playVideo = this.playVideo.bind(this);
  }

  componentDidMount() {
    this._initPlayer();
  }

  componentDidUpdate() {
    this._initPlayer();
  }

  componentWillUnmount() {
    if(this.hls) {
      this.hls.destroy();
    }
  }

  playVideo() {
    let { video : $video } = this.refs;
    $video.play();

    this.setState({isPlaying: true});
  }

  _initPlayer () {
    if(this.hls) {
      this.hls.destroy();
    }

    let { url, autoplay, hlsConfig } = this.props;
    let { video : $video } = this.refs;
    let hls = new Hls(hlsConfig);

    hls.attachMedia($video);

    hls.on(Hls.Events.MEDIA_ATTACHED, () => {
      hls.loadSource(url);

      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        if(autoplay) {
          $video.play();
        }
        else {
          $video.pause();
        }
      });
    });

    this.hls = hls;
  }

  render() {
    let { isMuted, isPlaying, playerId } = this.state;
    let { controls, width, height } = this.props;

    return (
      <div key={playerId}>
        {!isPlaying &&
          <span onClick={this.playVideo}></span>
        }
        <video ref="video"
          id={`react-hls-${playerId}`}
          controls={controls}
          width={width}
          height={height}
          muted={isMuted}
          playsinline>
        </video>
      </div>
    );
  }
}

export default VideoPlayer;
1

There are 1 answers

1
Lee이민규 On

I think the problem is component's lifecycle.

playVideo -> setState -> componentUpdate -> componentDidUpdate -> initPlayer

So the player is initialized every time when user plays the video.

You can override "shouldComponentUpdate" so prevent update with no initializing the player.