代码拉取完成,页面将自动刷新
同步操作将从 爬大树/facerig透明前置窗口 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
const settings = require('electron-settings')
const path = require('path')
const {
ipcRenderer
} = require('electron')
let Tray = require('electron').remote.Tray
const _ = require('lodash')
const Vue = require('vue/dist/vue')
const ELEMENT = require('element-ui')
Vue.use(ELEMENT)
let vm = new Vue({
el: '#main',
data: {
config: settings.get('config') || {
colorOffset: 2,
smoothValue: 1,
transparency: 0,
isLeft: true,
xOffset: 0
}
},
computed: {
canvasStyle() {
let {
isLeft,
xOffset,
transparency
} = this.config
return {
right: isLeft ? null : xOffset + 'px',
left: isLeft ? xOffset + 'px' : null,
opacity: 1 - transparency / 100
}
}
}
})
ipcRenderer.addListener('configChange', (event, config) => {
vm.config = config
})
// 获取驱动
async function getMediaSteam(isOpenAudio) {
let x = await navigator.mediaDevices.enumerateDevices()
let facerigDevice = _.find(x, {
label: settings.get('camera')||'FaceRig Virtual Camera'
})
if (!facerigDevice) {
let error = '未找到facerig虚拟摄像头设备,确保facerig广播已打开(启动时的boardcast选项)'
ipcRenderer.send('showBallon', {
content: error,
icon: 'error',
title: '获取虚拟摄像头时出错'
})
throw error
}
let audioId = isOpenAudio ? {
deviceId: 'default'
} : false
let option = {
audio: audioId,
video: {
deviceId: facerigDevice.deviceId
}
};
let mediaStream
try {
mediaStream = await navigator.mediaDevices.getUserMedia(option)
} catch (error) {
ipcRenderer.send('showBallon', {
content: '获取facerig虚拟摄像头时出错,可能是摄像头被占用,比如obs或者直播姬',
icon: 'error',
title: error.name
})
throw error
}
return mediaStream
}
//启动video
function startVideo(mediaStream) {
return new Promise(resolve => {
var video = document.querySelector('video');
video.onloadedmetadata = function (e) {
video.play();
resolve()
};
video.src = window.URL.createObjectURL(mediaStream);
})
}
//绘制一帧
function drawOneFrame() {
ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
// var imgdata = ctx.getImageData(0, 0, video.videoWidth, video.videoHeight);
// ctx.clearRect(0,0,canvas.width,canvas.height)
// ctx.putImageData(imgdata, 0, 0);
var imgdata = ctx.getImageData(0, 0, canvas.width, canvas.height);
//去除绿幕
let maxOffset = Math.pow(vm.config.colorOffset, 2)
let smooth = Math.pow(vm.config.colorOffset + vm.config.smoothValue, 2)
for (var i = 0; i < imgdata.height; ++i) {
for (var j = 0; j < imgdata.width; ++j) {
var x = i * 4 * imgdata.width + 4 * j
var r = imgdata.data[x],
g = imgdata.data[x + 1],
b = imgdata.data[x + 2],
a = imgdata.data[x + 3]
let offset = Math.pow(3 * (r), 2) + Math.pow(4 * (g - 255), 2) + Math.pow(2 * (b), 2)
// let offset = Math.abs(convert.rgb.hsv(r, g, b)[0] - convert.rgb.hsv(0, 255, 2)[0])
// let offset = Math.abs(r - green[0]) + Math.abs(g - green[1]) + Math.abs(b - green[2])
if (offset < maxOffset) {
imgdata.data[x + 3] = a = 0
} else if (offset < smooth) {
let percentage = 1 - Math.pow((smooth - offset) / 845325, 6)
imgdata.data[x + 3] = percentage * a
}
}
}
ctx.putImageData(imgdata, 0, 0);
}
function drawCanvas() {
window.video = document.querySelector('video')
window.canvas = document.querySelector('canvas')
let video = document.querySelector('video')
window.ctx = canvas.getContext('2d');
canvas.height = video.videoHeight
canvas.width = video.videoWidth
window.maxOffset = 50000
window.green = [0, 255, 0]
let fps=settings.get('fps')||30
setInterval(drawOneFrame,1000/fps);
}
async function start() {
//1. 获取驱动
let mediaStream = await getMediaSteam(settings.get('isOpenAudio'))
await startVideo(mediaStream)
// 启动video
drawCanvas()
}
//重载
function restart() {
clearInterval(drawOneFrame)
start()
}
ipcRenderer.on('restart', () => {
restart()
})
start()
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。