惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The GitHub Blog
The GitHub Blog
J
Java Code Geeks
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
罗磊的独立博客
MongoDB | Blog
MongoDB | Blog
B
Blog RSS Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
有赞技术团队
有赞技术团队
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Vercel News
Vercel News
腾讯CDC
博客园 - 聂微东
The Cloudflare Blog
F
Fortinet All Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
Last Week in AI
Last Week in AI
B
Blog

轶哥博客

blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog blog
blog
2021-04-06 · via 轶哥博客

接到一个需求,基于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的源代码已放到仓库: