Electron应用录制设备输入输出音频的可行方案咨询
实现Electron应用录制系统输出音频的方案
老兄,你说的完全没错——navigator.mediaDevices.getUserMedia确实只能搞定麦克风这类输入设备的音频捕获,没法直接抓取系统输出的声音。不过在Electron生态里,我们有专门的工具能解决这个问题,下面给你两种实用的实现方案,都是Electron开发里常用的思路:
方法一:用Electron的desktopCapturer直接捕获系统音频
这是最贴合Electron原生能力的方案,desktopCapturer是Electron官方提供的API,专门用于捕获桌面内容(包括系统音频流)。
实现步骤&代码示例
首先要确保你的Electron应用配置了必要的权限:在主进程的BrowserWindow配置里,webPreferences需要开启nodeIntegration(或者用预加载脚本暴露API,这里先给基础写法)。
然后在渲染进程里写捕获逻辑:
async function startSystemAudioRecording() { try { // 请求获取桌面音频源 const sources = await electron.desktopCapturer.getSources({ types: ['audio'], audio: true }); // 匹配系统音频源(不同系统的名称不一样,需要兼容) const systemAudioSource = sources.find(source => source.name.includes('系统音频') || source.name.includes('System Audio') || source.name.includes('BlackHole') // Mac上的虚拟音频设备名称 ); if (!systemAudioSource) { alert('没找到系统音频源!Windows请检查系统权限,Mac需要先安装BlackHole这类虚拟音频设备'); return; } // 创建包含系统音频的媒体流 const streamConstraints = { audio: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: systemAudioSource.id } } }; const audioStream = await navigator.mediaDevices.getUserMedia(streamConstraints); // 用MediaRecorder录制流(和你之前录麦克风的逻辑一致) const recorder = new MediaRecorder(audioStream); const audioChunks = []; recorder.ondataavailable = (event) => audioChunks.push(event.data); recorder.onstop = () => { const audioBlob = new Blob(audioChunks, { type: 'audio/webm' }); // 这里可以把录制好的音频保存到本地或者做其他处理 const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(audioBlob); downloadLink.download = 'system-audio-recording.webm'; downloadLink.click(); }; recorder.start(); console.log('系统音频录制开始啦!'); // 示例:5秒后自动停止录制 setTimeout(() => recorder.stop(), 5000); } catch (error) { console.error('捕获系统音频失败:', error); } }
系统兼容注意事项
- Windows:原生支持系统音频捕获,不需要额外安装工具,直接用就行
- macOS:苹果默认不允许直接捕获系统音频,必须先安装虚拟音频设备(比如BlackHole),然后在系统音频设置里把输出设备切换到这个虚拟设备,才能被
desktopCapturer识别 - Linux:大部分发行版需要依赖PulseAudio组件,配置好音频路由后就能正常捕获
方法二:用虚拟音频设备混合输入+输出音频
如果你需要同时录制麦克风输入和系统输出的声音,这种方案更合适——通过虚拟音频设备把两种音频流混合,再用getUserMedia捕获混合后的流。
实现步骤
- 安装虚拟音频设备:Windows用Voicemeeter,Mac用BlackHole,Linux用PulseAudio Loopback
- 系统音频设置配置:把系统输出和麦克风输入都路由到虚拟设备
- 在Electron里捕获这个虚拟设备的音频流
代码示例
async function startMixedAudioRecording() { try { // 获取所有音频输入设备 const audioDevices = await navigator.mediaDevices.enumerateDevices(); // 找到我们配置的虚拟音频设备 const virtualDevice = audioDevices.find(device => device.kind === 'audioinput' && (device.label.includes('BlackHole') || device.label.includes('Voicemeeter')) ); if (!virtualDevice) { alert('没找到虚拟音频设备,请先安装并完成系统配置'); return; } // 捕获虚拟设备的音频流 const streamConstraints = { audio: { deviceId: virtualDevice.deviceId } }; const mixedStream = await navigator.mediaDevices.getUserMedia(streamConstraints); // 后续录制逻辑和之前完全一致 const recorder = new MediaRecorder(mixedStream); const audioChunks = []; recorder.ondataavailable = (e) => audioChunks.push(e.data); recorder.onstop = () => { const mixedBlob = new Blob(audioChunks, { type: 'audio/webm' }); // 处理录制好的混合音频 const url = URL.createObjectURL(mixedBlob); const a = document.createElement('a'); a.href = url; a.download = 'mixed-audio-recording.webm'; a.click(); }; recorder.start(); console.log('混合音频录制开始!'); } catch (error) { console.error('捕获混合音频失败:', error); } }
额外提示
- 打包应用时,记得在
package.json里声明desktopCapture权限,避免权限问题 - 可以调整
MediaRecorder的配置参数来提升音频质量,比如指定比特率:new MediaRecorder(stream, { audioBitsPerSecond: 192000 }) - 不同系统的音频源名称差异较大,建议在代码里做更灵活的匹配逻辑,或者让用户手动选择设备
内容的提问来源于stack exchange,提问作者bSr




