React使用video.js播放RTMP流

video.js在6版本之后是和flash分开的,如果需要使用高版本的,需要额外安装videojs-flash

准备

项目有播放rtmp视频流的功能需求,所以搞来搞去还是想着用video.js这个库。

基于react,[email protected]

yarn add [email protected] @types/video.js

文档:video.js

页面中使用

页面中使用挺简单的

import React, { useMemo, useState, useEffect } from 'react';
import videojs from 'video.js';

// //样式文件注意要加上
import 'video.js/dist/video-js.css';

const Player: React.FC<any> = (props) => {

  const [videoNode, setVideoNode] = useState<any>();
  const [player, setPlayer] = useState<any>();

  const url = 'rtmp://58.200.131.2:1935/livetv/hunantv';

  // rtmp播放
  useMemo(() => {
    if (videoNode) {
      const videoJsOptions = {
        autoplay: true, // 自动播放
        language: 'zh-CN',
        preload: 'auto', // 自动加载
        errorDisplay: true, // 错误展示
        width: 475, // 宽
        height: 300,
        flash: {
          swf: '/video-js.swf',
        },
        sources: [
          {
            src: url,
            type: 'rtmp/flv', // 类型可加可不加,目前未看到影响
          },
        ],
      };
      const videoPlayer = videojs(videoNode, videoJsOptions);
      setPlayer(videoPlayer);
    }
  }, [videoNode]);

  useEffect(() => {
    return (() => {
      if (player) player.dispose()
    })
  }, [])

  return (
    <>
      <div style={{margin:50}}>
        <p>播放器</p>

        <video
          ref={(node) => {
            setVideoNode(node);
          }}
          id="videoPlay"
          className="video-js vjs-default-skin vjs-big-play-centered"
          width="100%"
          height="100%"
        >
          <track kind="captions" />
          <p className="vjs-no-js">您的浏览器不支持HTML5,请升级浏览器。</p>
        </video>
      </div>
    </>
  )
}

export default Player;

效果(页面中使用)

React使用video.js播放RTMP流_第1张图片

弹框使用

import React, { useMemo, useState, useEffect } from 'react';
import videojs from 'video.js';

// //样式文件注意要加上
import 'video.js/dist/video-js.css';
import { Modal } from 'antd';

const playerModal: React.FC<any> = (props) => {
  const { visible, onClose } = props;

  const [videoNode, setVideoNode] = useState<any>();
  const [player, setPlayer] = useState<any>();

  console.log(1);
  

  const url = 'rtmp://58.200.131.2:1935/livetv/hunantv';

  // rtmp播放
  useMemo(() => {
    if (videoNode) {
      const videoJsOptions = {
        autoplay: true, // 自动播放
        language: 'zh-CN',
        preload: 'auto', // 自动加载
        errorDisplay: true, // 错误展示
        width: 475, // 宽
        height: 300,
        flash: {
          swf: '/video-js.swf',
        },
        sources: [
          {
            src: url,
            type: 'rtmp/flv',
          },
        ],
      };
      const videoPlayer = videojs(videoNode, videoJsOptions);
      setPlayer(videoPlayer);
    }
  }, [videoNode]);

  useEffect(() => {
    return (() => {
      if (player) player.dispose()
    })
  }, [visible])

  const onPlayerClose = () => {
    console.log(1);
    
    onClose()
  }

  return (
    <>
      <Modal
        visible={visible}
        title="预览"
        onOk={onPlayerClose}
        onCancel={onPlayerClose}
        maskClosable={false}
      >
        <video
          ref={(node) => {
            setVideoNode(node);
          }}
          id="videoPlay"
          className="video-js vjs-default-skin vjs-big-play-centered"
          width="100%"
          height="100%"
        >
          <track kind="captions" />
          <p className="vjs-no-js">您的浏览器不支持HTML5,请升级浏览器。</p>
        </video>

      </Modal>

    </>
  )
}

export default playerModal;

效果(弹框)

React使用video.js播放RTMP流_第2张图片

报错啦

关闭弹框后报错!

this.el_.vjs_getProperty is not a function

主要是会一直报错,然后达到一定次数页面就崩了

React使用video.js播放RTMP流_第3张图片

解决

1、弹框没了的时候要销毁dispose,我这里放在useEffect中应该是没生效或者说不能解决吧

2、还要配合Modal的销毁子节点apidestroyOnClose

const onPlayerClose = () => {

    onClose()
	// 修改处
    setTimeout(()=>{
      if(player) player.dispose()
    },800)
  }

  return (
    <>
      <Modal
        visible={visible}
        title="预览"
        onOk={onPlayerClose}
        onCancel={onPlayerClose}
        maskClosable={false}
		// 修改处
        destroyOnClose
      >
        <video
          ref={(node) => {
            setVideoNode(node);
          }}
          id="videoPlay"
          className="video-js vjs-default-skin vjs-big-play-centered"
          width="100%"
          height="100%"
        >
          <track kind="captions" />
          <p className="vjs-no-js">您的浏览器不支持HTML5,请升级浏览器。</p>
        </video>

      </Modal>

    </>
  )

现在点击隐藏弹框也会出现报错,主要是我用了定时器销毁,如果不用定时器销毁的话,会有一定的视觉差。但是销毁之后就不会再报错了!

究极版

最后还是觉得这个报错不太爽,我就自己去改了一下源码,然后发布在gitee上,想用的话可以这样做

package.js

"video.js": "git+https://gitee.com/jx915/video.js.git"

playerModal.tsx

import React, { useState, useEffect } from 'react';
import videojs from 'video.js';

//样式文件注意要加上
import 'video.js/dist/video-js.css';
import { Modal } from 'antd';

const url = 'rtmp://58.200.131.2:1935/livetv/hunantv';

const playerModal: React.FC<any> = (props) => {
  const { visible, onClose } = props;

  const [videoNode, setVideoNode] = useState<any>();
  
  useEffect(() => {
    if (videoNode) {
      const videoJsOptions = {
        autoplay: true, // 自动播放
        language: 'zh-CN',
        preload: 'auto', // 自动加载
        errorDisplay: true, // 错误展示
        width: 475, // 宽
        height: 300,
        flash: {
          swf: '/video-js.swf',
        },
        sources: [
          {
            src: url,
            type: 'rtmp/flv', // 类型可加可不加,目前未看到影响
          },
        ],
      };
      videojs(videoNode, videoJsOptions)
    }
  }, [videoNode])

  const onPlayerClose = () => {
    onClose()
  }

  return (
    <>
      <Modal
        visible={visible}
        title="预览"
        onOk={onPlayerClose}
        onCancel={onPlayerClose}
        maskClosable={false}
        destroyOnClose
      >
        <video
          ref={(node) => {
            setVideoNode(node);
          }}
          id="videoPlay"
          className="video-js vjs-default-skin vjs-big-play-centered"
          width="100%"
          height="100%"
        >
          <track kind="captions" />
          <p className="vjs-no-js">您的浏览器不支持HTML5,请升级浏览器。</p>
        </video>

      </Modal>

    </>
  )
}

export default playerModal;

你可能感兴趣的:(大前端-React)