在基于vuecli3 与electron的框架外部,实现rtmp流的播放,为什么要写这篇文章,因为确实实现起来踩了很多坑,并没有像web那样导入videoJS 就能实现的,闲话不说,上代码 :

第一个坑 :

须要用到的库
vue-video-player
videojs-flash
留神:下面这个两个库 肯定要用npm装置。我试过,其余形式装置实现之后会这个谬误:the flash tech is undefined ,如果你遇到这个谬误,肯定先npm uninstall vue-video-player ,再重新安装一次即可。

第二个坑

播放rtmp须要flash的反对,Electron的实现须要代码加载flash的dll文件来取得反对,Electron的app类中有个getPath 办法,执行以下代码能获取本机的flash文件门路 :
app.getPath('pepperFlashSystemPlugin')
我的跑起来获取的地址是:C:WINDOWSsystem32MacromedFlashpepflashplayer64_32_0_0_414.dll
所以让electron反对flash代码 :

app.commandLine.appendSwitch('ppapi-flash-path', app.getPath('pepperFlashSystemPlugin'));

当然最好的计划是可能把dll文件间接打包到我的项目外面跟着我的项目一起走,通过在vue.config.js中增加以下代码实现

  pluginOptions: {    electronBuilder: {      builderOptions: {       ...        win: {          target: 'nsis',          icon: './public/app.ico',          extraResources: [                {                  "from": "resources/",                  "to": "./",                }          ]        }      }    }  }

把dll文件copy到resources文件夹下(根目录与vue.config.js同级)而后批改文件加载门路:

let plugins = ''  if( process.arch == 'x64' ){    plugins =process.env.WEBPACK_DEV_SERVER_URL? path.join(__dirname,`../resources/pepflashplayer64_32_0_0_238.dll`) :path.join(__dirname,`../pepflashplayer64_32_0_0_238.dll`)  }else{    plugins =process.env.WEBPACK_DEV_SERVER_URL? path.join(__dirname,`../resources/pepflashplayer32_29_0_0_238.dll`) :path.join(__dirname,`../pepflashplayer32_29_0_0_238.dll`)  }app.commandLine.appendSwitch('ppapi-flash-path', plugins)

第三个坑

以上的货色搞完根本能够实现播放了,然而打包之后发现不能够,看景象 像是加载不出flash,解决方案就是在启动 Electron 主过程的时候,启动一个本地 express 服务器,配置一下动态文件地址,而后渲染过程通过这个服务器拿到页面,在而后就能够启动 flash 了。
上代码:

'use strict'import { app, BrowserWindow,ipcMain } from 'electron' import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'// import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'const isDevelopment = process.env.NODE_ENV !== 'production'// Keep a global reference of the window object, if you don't, the window will// be closed automatically when the JavaScript object is garbage collected.let winlet allowPort =nullimport express from 'express'const net = require('net');async function portInUse(port){  return new Promise((resolve, reject)=>{      let server = net.createServer().listen(port);      server.on('listening',function(){          server.close();          resolve(port);      });      server.on('error',function(err){          if(err.code == 'EADDRINUSE'){              port++;              reject(err);          }      });          });}const tryUsePort = function(port,_portAvailableCallback){  portInUse(port).then((port)=>{      _portAvailableCallback(port);  }).catch((err)=>{      console.log(port+" ====被占用====:\n");      port++;      tryUsePort(port,_portAvailableCallback);  })  }tryUsePort(9080,function(port){  // do something ...  console.log(port+" ====端口:"+port+"可用====\n");  allowPort = port  // net.createServer().listen(port);  //解决flash本地file不平安问题  if (process.env.NODE_ENV === "production") {    let server = express();    server.use(express.static(__dirname));    server.listen(port);  }  const winURL = process.env.NODE_ENV === 'development'  ? `http://localhost:${allowPort}`   // : `file://${__dirname}/index.html`  //解决flash在file下不平安的问题  : `http://localhost:${allowPort}/index.html`  console.log(winURL)  const path = require('path')  let plugins = ''  if( process.arch == 'x64' ){    plugins =process.env.WEBPACK_DEV_SERVER_URL? path.join(__dirname,`../resources/pepflashplayer64_32_0_0_238.dll`) :path.join(__dirname,`../pepflashplayer64_32_0_0_238.dll`)  }else{    // plugins =process.env.WEBPACK_DEV_SERVER_URL? path.join(__dirname,`../resources/pepflashplayer32_29_0_0_238.dll`) :path.join(__dirname,`../pepflashplayer32_29_0_0_238.dll`)    plugins =app.getPath('pepperFlashSystemPlugin')   }console.log(app.getPath('pepperFlashSystemPlugin') )  app.commandLine.appendSwitch('ppapi-flash-path', plugins)  // Optional: Specify flash version, for example, v17.0.0.169  function createWindow() {    // Create the browser window.    win = new BrowserWindow({      width: 1000,      height: 580,      webPreferences: {        nodeIntegration: true,        plugins: true,        webSecurity: false //勾销跨域      },      autoHideMenuBar:true,      maximizable: false,      resizable: false,      frame: false,    })    if (process.env.WEBPACK_DEV_SERVER_URL) {      // Load the url of the dev server if in development mode      win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)      // if (!process.env.IS_TEST) win.webContents.openDevTools()    } else {      //批改前      createProtocol('app')      // win.loadURL('app://./index.html')      //批改后       win.loadURL(winURL)    }    win.webContents.openDevTools({ mode: 'detach' })    win.on('closed', () => {      win = null    })  }  // Quit when all windows are closed.  app.on('window-all-closed', () => {    // On macOS it is common for applications and their menu bar    // to stay active until the user quits explicitly with Cmd + Q    if (process.platform !== 'darwin') {      app.quit()    }  })  app.on('activate', () => {    // On macOS it's common to re-create a window in the app when the    // dock icon is clicked and there are no other windows open.    if (win === null) {      createWindow()    }  })  // This method will be called when Electron has finished  // initialization and is ready to create browser windows.  // Some APIs can only be used after this event occurs.  app.on('ready', async () => {    // if (isDevelopment && !process.env.IS_TEST) {    //   // Install Vue Devtools    //   try {    //     await installExtension(VUEJS_DEVTOOLS)    //   } catch (e) {    //     console.error('Vue Devtools failed to install:', e.toString())    //   }    // }    createWindow()  })

以上就是局部代码能看清楚解决逻辑,

第四个坑

port占用,通过net对象 写一个递归加一点判断 获取以后可用端口,代码如上

第五个坑

到当初你感觉完事大吉了,然而只能开心一会会,在某些状况下还是会呈现flash加载解体问题,这个时候你就要核查下你的flash 版本问题,我试过 30以上都不行29能够,举荐这个版本:pepflashplayer64_29_0_0_140.dll
pepflashplayer32_29_0_0_140.dll

备注:我的上述代码只是兼容了64位的电脑,如果须要兼容32位电脑自行加点判断即可