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

推荐订阅源

B
Blog RSS Feed
博客园_首页
N
News | PayPal Newsroom
有赞技术团队
有赞技术团队
The Hacker News
The Hacker News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
S
SegmentFault 最新的问题
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
P
Privacy & Cybersecurity Law Blog
AI
AI
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Schneier on Security
Schneier on Security
博客园 - 三生石上(FineUI控件)
月光博客
月光博客
量子位
Forbes - Security
Forbes - Security
爱范儿
爱范儿
云风的 BLOG
云风的 BLOG
SecWiki News
SecWiki News
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
T
Tor Project blog
Recorded Future
Recorded Future
A
About on SuperTechFans
J
Java Code Geeks
The Register - Security
The Register - Security
PCI Perspectives
PCI Perspectives
H
Hacker News: Front Page
V2EX - 技术
V2EX - 技术
S
Secure Thoughts
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
Y
Y Combinator Blog
AWS News Blog
AWS News Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
IT之家
IT之家
T
The Blog of Author Tim Ferriss
G
Google Developers Blog
C
CERT Recently Published Vulnerability Notes
L
LangChain Blog
F
Full Disclosure
Application and Cybersecurity Blog
Application and Cybersecurity Blog
The GitHub Blog
The GitHub 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 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 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 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的源代码已放到仓库: