轶哥

妄图改变世界的全栈程序员。

自助设备广告屏自动播放视频功能实现

接到一个需求,基于Electron开发Windows下的自助设备广告屏(上屏)自动播放视频的功能。设备下屏是带触控功能的屏幕,可以进行业务咨询、业务办理、视频咨询,上屏是不带触控功能的1080P屏幕。

%E8%87%AA%E5%8A%A9%E8%AE%BE%E5%A4%87.jpg 两个屏幕接入了同一个主机,下屏是主屏幕,上屏是分屏(扩展屏)。为了避免下屏进行视频咨询的时候,上屏播放视频的声音影响到对话,因此上屏播放视频功能需要开放相应的API接口,在下屏播放视频或进行音视频咨询的时候,相关的开发者能够通过API对上屏视频禁音。

由于我们已经开发了Android平台的同款设备,因此Electron平台需要和Android平台保持一致的API。

Android平台的双屏播放视频API接口如下:

// 视频播放地址/下载地址:  
SpeakerManager.videoUrl({0: "https://qiniu.laway.cn/mp4"})

// 视频静音  
SpeakerManager.videoMute()   

// 视频打开声音
SpeakerManager.videoUnMute() 

// 控制上屏声音
SpeakerManager.videoVolume(0.2) 

Electron获取副屏

const displays = screen.getAllDisplays()
const externalDisplay = displays.find((display) => {
  return display.bounds.x !== 0 || display.bounds.y !== 0
})

根据Electron官方文档说明,上述方法可以获取到副屏(扩展屏、上屏)。

创建上屏窗口并传递消息

if (externalDisplay) {
    const { width, height } = externalDisplay.workAreaSize
    const externalWin = new BrowserWindow({
      x: externalDisplay.bounds.x,
      y: externalDisplay.bounds.y,
      width,
      height,
      alwaysOnTop: false, // 总在最顶
      useContentSize: true,
      frame: false, // 显示标题栏
      resizable: false, // 不可改变尺寸
      center: true,
      minimizable: false,
      maximizable: true,
      focusable: true,
      kiosk: true,
      show: true,
      autoHideMenuBar: true,
      disableAutoHideCursor: true,
      webPreferences: {
        webSecurity: false,
        nodeIntegration: true,
        nodeIntegrationInWorker: true,
        nodeIntegrationInSubframes: true,
        contextIsolation: false
      }
    })
    externalWin.loadURL(`file://${__dirname}/video/index.html`)

    ipcMain.on('SpeakerManager', (_event, action, value) => {
      externalWin.webContents.send(action, value)
    })
}

单独打开一个窗口显示在副屏。监听渲染进程传递过来的SpeackerManager事件并传递给副屏。

自动循环播放视频、控制音量的页面实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>视频播放</title>
  <style>
    html,
    body,
    #loading,
    #my-player {
      padding: 0;
      margin: 0;
      width: 100%;
      height: 100%;
    }
  </style>
  <link href="video-js/video-js.min.css" rel="stylesheet">
  <script src="video-js/video.min.js"></script>
</head>

<body>
  <h1 id="loading">载入中...</h1>
  <video id="my-player" class="video-js" preload="auto" data-setup='{}'>
    <p class="vjs-no-js">
      To view this video please enable JavaScript, and consider upgrading to a
      web browser that
      <a href="https://videojs.com/html5-video-support/" target="_blank">
        supports HTML5 video
      </a>
    </p>
  </video>
  <script>
    const { ipcRenderer } = require("electron");

    var player = null;

    ipcRenderer.on('videoUrl', (e, list) => {
      var curr = 0;
      var options = {
        "width": "1920px",
        "height": "1080px",
        "autoplay": true,
        "controls": false,
        "muted": false,
        "sources": [{
          src: list[curr],
          type: 'video/mp4'
        }],
      };

      player = videojs('my-player', options, function onPlayerReady() {
        this.src({ type: 'video/mp4', src: list[curr] });
        this.load();
        document.getElementById('loading').style.display = 'none';
        this.play();
        this.on('ended', () => {
          curr++
          if (curr >= list.length) {
            curr = 0; //重新循环播放
          }
          this.src({ type: 'video/mp4', src: list[curr] });
          this.load();
          this.play();
        });
      });
    })

    ipcRenderer.on('videoMute', (e) => {
      if (player) player.muted(true)
    })

    ipcRenderer.on('videoUnMute', (e) => {
      if (player) player.muted(false)
    })

    ipcRenderer.on('videoVolume', (e, volume) => {
      if (player) player.volume(volume); //Volume range 0.0 to 1 (0.0, 0.1, 0.2 ...)
    })

  </script>
</body>

</html>

上述代码中,引入了开源项目video.js,通过ipcRenderer监听了相应的操作,实现对视频进行自动播放、循环播放,控制音量、禁音、取消禁音。

渲染进程注入控制方法

const { ipcRenderer } = require("electron");
var SpeakerManager = {
  videoUrl(list) { // 设置播放列表
    ipcRenderer.send('SpeakerManager', 'videoUrl', list)
  },
  videoMute() { // 静音
    ipcRenderer.send('SpeakerManager', 'videoMute')
  },
  videoUnMute() { // 取消静音
    ipcRenderer.send('SpeakerManager', 'videoUnMute')
  },
  videoVolume(num) { // 设置音量
    ipcRenderer.send('SpeakerManager', 'videoVolume', num)
  }
}
window.SpeakerManager = SpeakerManager

setTimeout(() => {
  SpeakerManager.videoUrl(['http://vjs.zencdn.net/v/oceans.mp4']) // 必须先启动
}, 3000)

setTimeout(() => {
  SpeakerManager.videoVolume(0.5) // 控制音量
}, 6000)

绑定到window全局变量,这样一来就可以实现和Android平台一致的API,开发人员可以一套代码同时运行在Windows平台和Android平台。

开源Demo

以上测试Demo的源代码已放到仓库:

https://github.com/yi-ge/electron-video

打赏
交流区

暂无内容

尚未登陆
发布
  上一篇 (Win10中通过WSL2开发基于Electron的Ubuntu应用程序)
下一篇 (记一次Intel AX201网卡卡顿问题解决)  

评论回复提醒