UNPKG

@hysc/boom-cpp-plugin

Version:

```markdown 使用示例,展示如何在 Electron 主进程中集成和使用该插件,使用 CommonJS 的引用方式:

363 lines (320 loc) 11.2 kB
const logger = require('electron-log') const os = require('os') const fs = require('fs') const path = require('path') const arch = os.arch() const platform = os.platform() const isWindows = () => platform === 'win32' const isMac = () => platform === 'darwin' /* * @Author: baijiayun.com * @Date: 2023-08-10 15:01:53 * @Description: 这是cpp 插件的 bridge 层, 单例 */ class CppPluginBridge { constructor() { if (CppPluginBridge.instance) { return CppPluginBridge.instance } this.mainWindow = null this.instance = null CppPluginBridge.instance = this } bindTargetWindow(mainWindow) { this.mainWindow = mainWindow } /** * * @param {string} winArc * windows 应用架构,只能为 x64 或者 x86 默认是x86 * mac arm传递 arm x86传递 x86 默认 x86 * @returns */ init(winArc) { if (this.instance) { return this.instance } let lib let dllPath let fileMidPath = `${platform}-${arch}` if (isWindows()) { if (arch === 'x64') { dllPath = path.resolve(process.resourcesPath, '../node_modules/@hysc/boom-cpp-plugin/cppPlugin', fileMidPath); process.env.PATH = dllPath + ';' + process.env.PATH; lib = require(`../cppPlugin/win32-x64/bjy_electron_plugin.node`) } else { dllPath = path.resolve(process.resourcesPath, '../node_modules/@hysc/boom-cpp-plugin/cppPlugin', fileMidPath); process.env.PATH = dllPath + ';' + process.env.PATH; lib = require(`../cppPlugin/win32-ia32/bjy_electron_plugin.node`) } } else if (isMac()) { dllPath = path.resolve(process.resourcesPath, '../node_modules/@hysc/boom-cpp-plugin/cppPlugin', fileMidPath); let exists = fs.existsSync(dllPath); console.log('cpp plugin dllPath:', dllPath, 'exists:', exists) if ((os.arch() === 'arm64' && exists)) { lib = require(`../cppPlugin/darwin-arm64/bjy_electron_plugin.node`) } else { fileMidPath = 'darwin-x64'; lib = require(`../cppPlugin/darwin-x64/bjy_electron_plugin.node`) } dllPath = path.resolve(process.resourcesPath, '../node_modules/@hysc/boom-cpp-plugin/cppPlugin', fileMidPath); exists = fs.existsSync(dllPath); if (!exists) { console.error('cpp plugin not exists, please check the path:', dllPath) } } if (lib) { this.instance = new lib.BJYCppPlugin() this.instance.createEngineInstance() if (isMac()) { this.setOnLogEventCallback() } logger.log('init cpp plugin success, dllPath:', dllPath) return } else { logger.log('init cpp plugin failed', dllPath) throw new Error('init cpp plugin failed') } } initWithPath(filePath) { if (this.instance) { return this.instance } let lib let dllPath let fileMidPath = `${platform}-${arch}` if (isWindows()) { if (arch === 'x64') { lib = require(`../cppPlugin/win32-x64/bjy_electron_plugin.node`) } else { lib = require(`../cppPlugin/win32-ia32/bjy_electron_plugin.node`) } } else if (isMac()) { if ((os.arch() === 'arm64')) { lib = require(`../cppPlugin/darwin-arm64/bjy_electron_plugin.node`) } else { lib = require(`../cppPlugin/darwin-x64/bjy_electron_plugin.node`) } } if (lib) { this.instance = new lib.BJYCppPlugin() this.instance.createEngineInstance() if (isMac()) { this.setOnLogEventCallback() } logger.log('init cpp plugin success, dllPath:', dllPath) return } else { logger.log('init cpp plugin failed', dllPath) throw new Error('init cpp plugin failed') } } // ======================= event callback ======================= // /** * cpp 音频采集事件回调 * @param {*} data * @param {*} sampleRate * @param {*} channel * @param {*} timestamp */ audioEventCallback(data, sampleRate, channel, timestamp) { if (this.mainWindow) { this.mainWindow.webContents.send('onAudioData', data, sampleRate, channel, timestamp) } else { logger.log('mainWindow is null, audioEventCallback', sampleRate) } } /** * cpp 音频采集错误回调 * @param {*} code * @param {*} msg */ audioCaptureErrorCallback(code, msg) { logger.log('cpp audio plugin capture audio error', code, msg) logger.log('stop audio capture') this.stopCapture() logger.log('restart audio capture') const res = this.instance.startAudioCapture(0, false) logger.log('start audio plugin result', res) } /** * cpp 窗口全屏事件回调 * @param {*} isFullScreen * @param {*} fullScreenWId */ async fullScreenCallBack(isFullScreen, fullScreenWId) { logger.log('isFullScreen', isFullScreen, 'fullScreenWId', fullScreenWId) const id = `window:${fullScreenWId}:0` logger.log('send select source to webContents', id) this.mainWindow.webContents.send('onFullScreen', { id }, isFullScreen) } setOnLogEventCallback() { if (this.instance) { this.instance.setEventCallback('onLog', this.cppLogCallback.bind(this)) } } cppLogCallback(logs) { logger.log('cpp plugin logs', logs) } /** * 设置窗口全屏事件回调 */ setWinPluginEventCallBack() { if (this.instance) { console.log('set win plugin event callback') this.instance.setEventCallback('onWindowFullScreenEvent', this.fullScreenCallBack.bind(this)) } } setAudioPluginEventCallback() { if (this.instance) { this.instance.setEventCallback('onCapturedRawAudioFrame', this.audioEventCallback.bind(this)) this.instance.setEventCallback('onAudioCaptureError', this.audioCaptureErrorCallback.bind(this)) } } // ======================= event callback end ======================= // bringWindowToTop(wid) { if (this.instance) { const isNumber = !Number.isNaN(Number(wid)) if (isNumber) { logger.log('bring target window to top') return this.instance.bringWindowToTop(Number(wid)) } else { logger.log('bring window to top failed, wid is not a number') } } } /** * 采集系统声音 * @param {Number} sid sourceId 指定窗口ID,设置为0表示采集当前运行进程本身 * @param {Boolean} onlySourceId 采集模式,true表示只采集指定窗口进程 false表示采集除了本地窗口进程 */ startAudioCapture(sid, onlySourceId) { logger.log('startCapture', sid, onlySourceId) if (this.instance) { const isNumber = !Number.isNaN(Number(sid)) if (isNumber) { const res = this.instance.startAudioCapture(Number(sid), onlySourceId) logger.log('startCapture result', res) if (res < 0) { logger.log('startCapture failed') this.stopCapture() this.mainWindow.webContents.send('onAudioCaptureError', { failed: true, res }) } } else { logger.log('startCapture failed, sid is not a number') } } } /** * 检测视频窗口变化 * @param {*} wid */ startWindowDetector(wid, sourceName) { logger.log('startWindowDetector', wid, sourceName) if (this.instance) { const isNumber = !Number.isNaN(Number(wid)) if (isNumber) { const res = this.instance.startWindowDetector(Number(wid)) logger.log('start window capture res', res) if (res < 0) { logger.log('start window capture failed') this.stopWindowDetector() this.mainWindow.webContents.send('onWindowCaptureError', { failed: true, res }) } } else { logger.log('start window capture failed, wid is not a number') } } } stopWindowDetector() { if (this.instance) { this.instance.stopWindowDetector() } } stopCapture() { if (this.instance) { this.instance.stopAudioCapture() } } destroy() { if (this.instance) { this.stopCapture() this.stopWindowDetector() this.releaseAudioDeviceMgr() this.instance.destroyEngineInstance() this.instance = null this.mainWindow = null } } // ================ 音频管理 ==================== // initAudioDeviceManage() { this.instance.audioDeviceMgrInitialize() } /** * 设置当前音频设备 * * @param {String} speakerName 扬声器名称 * @param {String} micName 麦克风名称 */ setAudioDevice(speakerName, micName) { return this.instance.setAudioDevice(speakerName, micName) } /** * 设置扬声器音量 * @param {Number} volume * @returns {Boolean} true 成功 false 失败 */ setSpeakerVolume(volume) { return this.instance.setSpeakerVolume(volume) } /** * 获取扬声器音量 * @returns {Number} */ getSpeakerVolume() { return this.instance.getSpeakerVolume() } /** * 设置麦克风音量 * @param {Number} volume * @returns {Boolean} true 成功 false 失败 */ setMicVolume(volume) { return this.instance.setMicVolume(volume) } /** * 获取麦克风音量 * @returns {Number} */ getMicVolume() { return this.instance.getMicVolume() } /** * 扬声器是否静音 * @returns {Boolean} true 静音 false 未静音 */ isSpeakerMute() { return this.instance.isSpeakerMute() } /** * 麦克风是否静音 * @returns {Boolean} true 静音 false 未静音 */ isMicMute() { return this.instance.isMicMute() } enableMicrophoneDevice() { if (isWindows()) { return this.instance.enableMicrophoneDevice() } else { return true } } releaseAudioDeviceMgr() { if (isWindows()) { return this.instance.releaseAudioDeviceMgr() } } // ==================================== // } module.exports = CppPluginBridge