前言:chrome访问windows摄像头只有两种情况下符合(1、https协议下 2、谷歌浏览器白名单),由于项目问题,需要在http协议环境下访问摄像头。于是百度了很多方法,大部分都没有生效,也可能是我配置有问题
一、环境介绍
1、https下浏览器中音视频权限都是可访问的
2、http下浏览器是禁止访问的权限
于是我需要在electron中给应用程序能够访问音视频的权限,在electron中http能够访问音视频权限的我找到了三种方法
1、使用内置模块protocol的registerSchemesAsPrivileged方法
2、指定网址当成安全协议
3、设置自定义权限的检查和处理权限请求,来管理 electron 中 web 页面的权限请求
二、解决方案
1、官网描述:protocol.registerSchemesAsPrivileged内置方法
具体使用方法如下:
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
{
scheme: 'http',
privileges:
{
standard: true,
secure: true,
bypassCSP: true,
allowServiceWorkers: true,
supportFetchAPI: true,
corsEnabled: true,
stream: true
}
}
])
把指定的协议当成安全的协议,从而去调用本机摄像头等设备,开启后该协议所有网址都会被视为安全网址,安全性会降低。此方法我本地调试后依旧无法获取到流视频
2、指定网址当成安全协议
第二个参数为数组,可以设置多个指定网址为安全协议
const { app } = require('electron')
app.commandLine.appendSwitch('unsafely-treat-insecure-origin-as-secure', ['http://172.16.30.151:8086', 'http://localhost:8086'])
此方法设置后依旧行不通,chrome中设置了白名单后也不行
3、自定义请求权限可以响应权限
session.setPermissionCheckHandler(handler):设置回调函数来自定义权限的检查,
每当 electron 中的 web 页面请求权限时,这个回调函数会被调用。你可以在这个回调函数中决定是否允许或拒绝该权限。回调函数的签名为:
handler(webContents, permission, callback)
webContents
:表示请求权限的 Web 页面的 WebContents 对象。permission
:表示请求的权限类型,例如'media'
(访问摄像头和麦克风)、'geolocation'
(地理位置)、'notifications'
(通知)等。callback
:一个回调函数,你可以调用它来传递是否允许该权限的决定,形如callback(true)
(允许)或callback(false)
(拒绝)。session.setPermissionRequestHandler(handler):允许设置回调函数来处理权限请求的用户界面。当 electron 中的 web 页面请求权限并且
session.setPermissionCheckHandler
未决定是否允许该权限时,该回调函数会被调用。回调函数的签名为:
handler(webContents, permission, callback)
,参数和返回值与session.setPermissionCheckHandler
的回调函数相同。这两个都是用于管理 electron 中 web 页面的权限请求的 api
const { BrowserWindow } = require('electron')
const webBrowserWindow = new BrowserWindow({
width: 1600,
height: 1200,
webPreferences: {
contextIsolation: false, // 沙箱 上下文隔离
nodeIntegration: true, // 允许html页面上的 javascipt 代码访问 nodejs 环境 api
// preload: path.join(__dirname, 'preload.js'),
// 允许访问摄像头和麦克风
allowMediaDevices: true,
// backgroundThrottling: false, // 设置应用在后台正常运行
}
})
// 获取当前窗口的会话对象
const session = webBrowserWindow.webContents.session
// 响应 session 的权限请求
session.setPermissionRequestHandler((_, permission, callback) => {
// if (webBrowserWindow.webContents.getURL() === 'http://hostlocal:8086/') {
// return callback(true)
// }
// 默认响应全部请求
callback(true)
})
session.setPermissionCheckHandler(() => true)
// 初始化摄像头
initCamera () {
try {
// 获取 windows 可用媒体设备信息
navigator.mediaDevices.enumerateDevices().then(devices => {
// console.log('devices', devices)
// 根据设备id判断具体使用哪个摄像头
for (const key in devices) {
if (devices[key].kind === this.deviceKind) {
this.device = devices[key]
break
}
}
})
} catch (error) {
this.errorCamera(error)
}
}
// 打开摄像头
async openCamera () {
// 如摄像头已打开,则直接返回
if (this.isCameraOpen) return false
// 约束条件
const constraints = {
video: {
frameRate: {
ideal: 20
},
device: this.device.deviceId
}
}
try {
// 获取流视频
const stream = await navigator.mediaDevices.getUserMedia(constraints)
if (stream) {
this.showStream(stream)
} else {
$message('未获取到摄像头')
}
} catch (error) {
this.errorCamera(error)
}
}
最终可以通过navigator.mediaDevices.getUserMedia()获取到流视频,是否授权音视频可在上述回调函数中自行根据业务逻辑控制。
注意:该方法是在electron社区论坛中找到。这个目前我只用于本地调试使用。具体风险暂未可知