react 封装一个flvjs

import React, { Component, PureComponent } from 'react';
import PropTypes from 'prop-types';
import flvjs from 'flv.js';
import waiting from '@/assets/waiting.jpg';
/**
 * react component wrap flv.js
 */
export default class Reflv extends PureComponent<any, any> {
  static propTypes = {
    className: PropTypes.string,
    style: PropTypes.object,
    /**
     * media URL, can be starts with 'https(s)' or 'ws(s)' (WebSocket)
     */
    url: PropTypes.string,
    /**
     * media type, 'flv' or 'mp4'
     */
    type: PropTypes.oneOf(['flv', 'mp4']).isRequired,
    /**
     * whether the data source is a **live stream**
     */
    isLive: PropTypes.bool,
    /**
     * whether to enable CORS for http fetching
     */
    cors: PropTypes.bool,
    /**
     * whether to do http fetching with cookies
     */
    withCredentials: PropTypes.bool,
    /**
     * whether the stream has audio track
     */
    hasAudio: PropTypes.bool,
    /**
     * whether the stream has video track
     */
    hasVideo: PropTypes.bool,
    /**
     * total media duration, in milliseconds
     */
    duration: PropTypes.bool,
    /**
     * total file size of media file, in bytes
     */
    filesize: PropTypes.number,
    /**
     * Optional field for multipart playback, see MediaSegment
     */
    segments: PropTypes.arrayOf(
      PropTypes.shape({
        /**
         * indicates segment duration in milliseconds
         */
        duration: PropTypes.number.isRequired,
        /**
         * indicates segment file size in bytes
         */
        filesize: PropTypes.number,
        /**
         * indicates segment file URL
         */
        url: PropTypes.string.isRequired,
      }),
    ),
    /**
     * @see https://github.com/Bilibili/flv.js/blob/master/docs/api.md#config
     */
    config: PropTypes.object,
  };

  init = () => {
    let $video = this.inputRef;
    if ($video) {
      if (flvjs.isSupported()) {
        const {
          url,
          type,
          isLive,
          cors,

          hasAudio = false,
        } = this.props;
        let player = flvjs.createPlayer(
          {
            url,
            type,
            isLive,
            hasAudio,
            cors,
          },
          this.props.config || {
            enableStashBuffer: false, // 关闭IO隐藏缓冲区
            stashInitialSize: 128, // 减少首帧显示等待时长
          },
        );
        player.attachMediaElement($video);
        player.load();
        if (this.props.autoPlay) {
          player.play();
        }
        this.player = player;
      }
    }
  };
  inputRef: any;
  player: any;

  componentWillUnmount() {
    if (this.player) {
      this.player.unload();
      this.player.detachMediaElement();
    }
  }

  componentWillReceiveProps(nextProps: any, nextState: any) {


  }
  componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>, snapshot?: any): void {
    if (prevProps.url != this.props.url||prevProps.type != this.props.type) {
      this.destroyFlv();
      this.init();
    }
  }

  destroyFlv = () => {
    if (this.player) {
      this.player.pause();
      this.player.unload();
      this.player.detachMediaElement();
      this.player.destroy();
      this.player = null;
    }
  };

  listenVideoErr = () => {
    const that = this;
    this.player.on(flvjs.Events.ERROR, (errorType, errorDetail, errorInfo) => {
      console.log('触发了错误')
      try {
        console.log('errorType', errorType);
        console.log('errorDetail', errorDetail);
        console.log('errorInfo', errorInfo);
        // 视频出错后销毁重建
        that.player.unload();
        that.player.load();
        if (that.props.autoPlay) {
          that.player.play();
        }
      } catch { }
    });


  };

  listenVideoErrStatic = () => {
    const that = this;
    // 视频断流
    this.player.on('statistics_info', function (res) {

      if (that.state.lastDecodedFrames === 0) {
        that.setState({ lastDecodedFrames: res.decodedFrames });
        console.log('触发了视频断流1')
        return;
      }
      if (that.state.lastDecodedFrames != res.decodedFrames) {
        that.setState({ lastDecodedFrames: res.decodedFrames });
      } else {
        console.log('触发了视频断流销毁')
        that.setState({ lastDecodedFrames: 0 });
        that.player.unload(); // 卸载当前视频源
        that.player.load();
      }
    });
  }

  constructor(props: any) {
    super(props);
    this.state = {
      lastDecodedFrames: 0,
    };
  }

  componentDidMount(): void {
    this.init();
    this.listenVideoErr();
    //this.listenVideoErrStatic();
  }

  render() {
    const { className, style } = this.props;
    return (
      <video
        autoPlay={this.props.autoPlay}
        className={className}
        controls={true}
        poster={waiting}
        style={Object.assign(
          {
            width: this.props.width,
            height: this.props.height,
          },
          style,
        )}
        ref={(el) => {
          this.inputRef = el;
        }}
        muted={this.props.autoPlay}
      />
    );
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值