主要过程:
使用依赖:
服务端:
rtsp2web
作者使用ffmepg将rtsp流转化成了mpeg/mpeg2的播放格式。
这里贴一下搜到的:
客户端(浏览器端):
@cycjimmy/jsmpeg-player
这个是基于jsmpeg封装的,所以同时支持jsmpeg的拓展属性,但是使用起来更加方便简洁
具体代码实现:
服务端代码:
就是引用一下依赖,没有其他的了
// 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渲染,
这个配置项可以在依赖文档中找到。