天天看點

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;