赞
踩
近期有项目需求前端播放rtsp视频流,项目是由electron+vue3搭建,没有后端,因此需要在前端实现解析rtsp流及播放,经过多方考察最后选用了ffmpeg+jsmpeg方案实现,具体实现是参考了@牧也の旅行 大佬的这篇文章 原文地址 实现的,感谢@牧也の旅行 一直在回复我的各种小白问题,这里记录一下做这个功能时遇到的问题和解决方法:
主进程中的程序及其他配置参见原文,这里就不赘述了。
1,原文是单路播放,我的需求需要多路播放:
本来预想是展示16路,查资料也是说可以显示16路,但实际发现浏览器中只能稳定显示8路,超过后浏览器经常会报WARNING: Too many active WebGL contexts. Oldest context will be lost.
并自动从第一路开始销毁,无法恢复(这里一直没有找到解决办法):
采用的方式是在vue组件中预先设置好canvas,id就是rtsp流的通道号
<div v-for="i in 8" :key="i" style="padding:5px;" >
<canvas class="preview-video-canvas" :id="'chn'+(i-1).toString(16)"></canvas>
</div>
编写一个video.js 来播放多路
const {ipcRenderer} = require('electron'); import MpegPlayer from 'jsmpeg-player' export class videoRtspPlayer { #pc; constructor(elements, opts = {}) { this.opts = opts; this.#pc = []; this.videoElement = Array.from(elements); this.baseUrl = this.init(this.opts); } /** * 创建视频播放url * @param {Object} opts 传入rtsp地址 * @return {Promise<void>} */ init(opts){ return `rtsp://${opts.addr}:666/live/`; } /** * 播放 * @return {Promise<void>} */ play() { this.videoElement.forEach(async (video,index)=>{ setTimeout(()=>{ let pc; const url =`${this.baseUrl}${video.id}`; const res = ipcRenderer.sendSync('openRtsp', url,index); if (res.code === 200) { // pc = new MpegPlayer.VideoElement(video, res.ws); 这里由于我的播放位置是固定的,因此使用 MpegPlayer.Player方法 ,与原文不同 pc = new MpegPlayer.Player(res.ws,{ canvas:video, videoBufferSize:1024*1024, //增加一些缓存 }) pc['rtsp'] = url; } pc && this.#pc.push(pc); },index*100) }) } /** * 停止 */ stop() { console.log(this.#pc) this.#pc.forEach(pc=>{ pc.stop(); ipcRenderer.sendSync('closeRtsp', pc.rtsp); }) this.#pc = []; } }
electron/main.js中稍作改动,端口改为固定8个,不再使用addPort++;
vue中调用
import {videoRtspPlayer} from "../../common/Video"; let videoPlayer; const netState = { addr: 你的rtsp地址 } const initVideo = () =>{ //开启视频预览 let videos = document.getElementsByClassName('preview-video-canvas'); videoPlayer = new videoRtspPlayer(videos,netState); } onMounted(() => { initVideo(); videoPlayer.play() }) onUnmounted(()=>{ videoPlayer.stop(); })
至此,在开发环境,我可以正常开启8路rtsp视频预览了,通过配置Stream的尺寸,减小播放窗口,我的内存和cpu占用还算理想。
2、接着我就遇到了这个项目最大的坑:打包。打包后的程序,安装完运行起来一直报:
A JavaScript error occurred in the main process
Uncaught Exception:Error: spawn D: ldeaProjects md scs dist electron ffmpeg.exe ENOENTat ChildProcess.handle.onexit (node:internal/child process:283:19)at onErrorNT (node:internal/child process:478:16)at process.processTicksAndRejections (node:internal/process/task queues:83:21),
总的意思就是找不到 ffmpeg.exe 这个文件,查了一整天资料研究打包修改配置,我是使用electron-builder打包,配置文件在vue.config.js中,关键步骤如下:
1)将 ffmpeg.exe 拷贝到项目根目录;
2)配置中添加:
electronBuilder: {
...
builderOptions:{
...
"asar": true,
"extraResources":['ffmpeg.exe'],
...
}
...
}
这样打包安装后,ffmpeg.exe就会出现在安装目录的resources/下,
electron/main.js中下面这句需要修改
// ffmpegPath: app.isPackaged ? ffmpegPath.replace('app.asar', 'app.asar.unpacked') : ffmpegPath, //改为下面那句
ffmpegPath: app.isPackaged ? ffmpegPath.replace('app.asar', '') : ffmpegPath,
之后打包-安装-播放成功~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。