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}
      />
    );
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的弹窗组件示例: ```javascript import React, { useState } from "react"; const Modal = ({ title, content, onClose }) => { const [isOpen, setIsOpen] = useState(true); const handleModalClose = () => { setIsOpen(false); onClose(); }; return ( <div className={`modal ${isOpen ? "is-active" : ""}`}> <div className="modal-background" onClick={handleModalClose} /> <div className="modal-card"> <header className="modal-card-head"> <p className="modal-card-title">{title}</p> <button className="delete" aria-label="close" onClick={handleModalClose} /> </header> <section className="modal-card-body">{content}</section> </div> </div> ); }; export default Modal; ``` 这个弹窗组件包括一个标题和内容,可以通过设置 `isOpen` 属性来控制显示和隐藏。在关闭弹窗时,我们需要调用 `onClose` 回调函数来通知父组件。 使用方式: ```javascript import React, { useState } from "react"; import Modal from "./Modal"; const App = () => { const [isModalOpen, setIsModalOpen] = useState(false); const handleOpenModal = () => { setIsModalOpen(true); }; const handleCloseModal = () => { setIsModalOpen(false); }; return ( <div> <button onClick={handleOpenModal}>Open Modal</button> <Modal title="Modal Title" content="This is the content of the modal." onClose={handleCloseModal} isOpen={isModalOpen} /> </div> ); }; export default App; ``` 在这个例子中,我们在父组件中定义了一个 `handleOpenModal` 回调函数来打开弹窗,以及一个 `handleCloseModal` 回调函数来关闭弹窗。我们将这些回调函数传递给 `Modal` 组件,并通过 `isOpen` 属性来控制弹窗的显示和隐藏。 注意,这只是一个简单的示例,实际应用中可能需要更多的功能和自定义选项。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值