天天看点

React使用video.js播放RTMP流

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

更新

2020.9.21

publish

:已更新至

npm

仓库

  1. npm包:

    npm i @antelopecloud/components

  2. README.md

2020.9.9

improve

:一些优化

  1. 第一版功能完成
  2. 作为组件,完成打包(暂未发布)
  3. 新增使用文档

    README.md

2020.9.5

feat

:新增独立组件,地址FlashPlayer

  1. 功能:播放

    RTMP

    流,新增重连机制
  2. 未全部完成,可以做独立组件自行修改
  3. 使用方法看

    FlashPlayer.stories.tsx

    就行了

2020.8.5

docs

:新增高版本使用说明;新增

@ly-utils/videojs-flash

库解决后续报错问题

React使用video.js播放RTMP流

准备

项目有播放

rtmp

视频流的功能需求,所以搞来搞去还是想着用

video.js

这个库。

基于

react

,

[email protected]

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

建议使用 (使用这个库的话后续代码记得修改一下引用库名称)

yarn add @ly-utils/video.js -D
           

文档: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流

弹框使用

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流

报错啦

关闭弹框后报错!

this.el_.vjs_getProperty is not a function

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

React使用video.js播放RTMP流

解决

1、弹框没了的时候要销毁

dispose

,我这里放在

useEffect

中应该是没生效或者说不能解决吧

2、还要配合

Modal

的销毁子节点

api

destroyOnClose

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"
           

或者(使用这个库的话后续代码记得修改一下引用库名称)

yarn add @ly-utils/video.js -D
           

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;