海康摄像头视频流接入

491 阅读2分钟

主要过程:

使用依赖:

服务端:

rtsp2web

www.npmjs.com/package/rts…

作者使用ffmepg将rtsp流转化成了mpeg/mpeg2的播放格式。

这里贴一下搜到的:

blog.csdn.net/m0_60259116…

客户端(浏览器端):

@cycjimmy/jsmpeg-player

www.npmjs.com/package/@cy…

这个是基于jsmpeg封装的,所以同时支持jsmpeg的拓展属性,但是使用起来更加方便简洁

github.com/phoboslab/j…

具体代码实现:

服务端代码:

就是引用一下依赖,没有其他的了

// index.js

const RTSP2web = require('rtsp2web')

// 服务端长连接占据的端口号;端口号可以自定义
const port = 9998

let videoSize = '1920x1080'

new RTSP2web({
  port,
  videoSize
})

然后用node index.js起这个服务

客户端(浏览器端)代码:

这里封装了一个react组件,组建的props接收的videoUrl是海康视频地址,海康摄像头的rtsp地址通常格式为:“rtsp://username:password@192.168.1.64:554//Streaming/Channels/1”

其中1 代表主流,2代表子流

import { useState, useRef, useEffect, memo } from 'react';
import JSMpeg from '@cycjimmy/jsmpeg-player';
import './index.less';
interface Iprops {
  valIp: string;
}
const WS_URL = 'ws://42.193.174.155:9999'; //部署的node服务的地址
const VideoTest = (props: Iprops) => {
  const videoRef = useRef(null);
  const playerRef = useRef<any>(null);
  const [posterShow, setPosterShow] = useState(true);
  const { valIp } = props;
  const videoPlay = (videoUrl: string) => {
    if (playerRef.current) { //调用前先判断是否已经有创建实例,有就销毁
      playerRef.current.destroy();
    }
    playerRef.current = new JSMpeg.VideoElement(
      videoRef.current,
      `${WS_URL}/rtsp?url=${btoa(`${videoUrl}`)}`,
      {
        autoplay: true,
        picMode: true,
      },
      {
        audio: false,
        disableGl: true,
        onVideoDecode: (e) => {
          setPosterShow((val) => {
            if (val) {
              return false;
            }
            return val;
          });
        },
        onSourceEstablished: (e) => {
          setTimeout(() => {
            setPosterShow(false);
          }, 500);
        },
      },
    );
  };
  useEffect(() => {
    playerRef?.current?.destroy();
    videoPlay(valIp);

    return () => {
      if (playerRef.current) {
        playerRef?.current?.destroy();
        playerRef.current = null;
      }
    };
  }, [valIp]);
  return (
    <div className="mpeg-wrapper">
      <div ref={videoRef}></div>
      {posterShow ? <div className="poster"></div> : null}
    </div>
  );
};
//memo对组建进行缓存,防止重复创建
export default memo(VideoTest);
.mpeg-wrapper {
  width: 100%;
  height: 100%;
  position: relative;
  > div,
  canvas {
    width: 100%;
    height: 100%;
  }
  .poster {
    position: absolute;
    left: 0;
    top: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #000;
    font-size: 30px;
    z-index: 9;
    background-image: url('~@/assets/images/player_load.png'); //视频加载时的默认图片
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }
}

这里类名为poster的div,是一个图片,默认展示,在播放器接收到数据或者解码成功时隐藏。这样改善了初始化时候视频界面白屏的效果。

项目踩坑点:

项目中我用了react-unity-webgl来加载unity模型,当播放器切换视频源,累计达到12次的时候,模型就会消失。

这个坑点排查了一天,发现浏览器有一个警告:

WARNING: Too many active WebGL contexts. Oldest context will be lost.

这个其实是播放器jsmpeg的问题,因为它渲染视频默认启用的是webgl,每次切换视频都会用webgl渲染,而react-unity-webgl也是用的webgl渲染,这才出现了上述模型消失的问题,解决办法就是关闭webgl渲染,

这个配置项可以在依赖文档中找到。