Chrome音频录制扩展无法捕获Google Meet麦克风音频,需实现扬声器与麦克风音频分文件录制
Chrome音频录制扩展无法捕获Google Meet麦克风音频,需实现扬声器与麦克风音频分文件录制
看起来你现在的核心问题是:现有扩展能捕获Chrome标签页的扬声器输出,但拿不到Google Meet里的麦克风音频,还得把两个音频流分别存成mic.wav和speaker.wav对吧?我来给你拆解下修改步骤,都是针对Manifest V3扩展的实操方案:
第一步:补全扩展权限(必须先改这个)
你的manifest.json里现在的权限不够,要捕获标签页音频和本地麦克风,得加上两个关键权限:
tabCapture:专门用于捕获Chrome标签页的音频/视频流audioCapture:用于获取本地麦克风的音频权限
修改后的权限部分大概是这样:
"permissions": ["offscreen", "contextMenus", "activeTab", "tabCapture", "audioCapture"]
第二步:拆分音频捕获逻辑(核心改动)
之前你应该是只捕获了标签页的音频流,但Google Meet的麦克风是本地输入设备,和标签页输出流是两个独立的媒体流,得分开捕获:
- 标签页扬声器流:用
chrome.tabCapture.capture获取,对应Meet里的其他参与者声音+系统播放的音频 - 本地麦克风流:用
navigator.mediaDevices.getUserMedia获取,对应你自己的麦克风输入
具体逻辑(放到Offscreen文档里,因为Manifest V3不允许在Popup直接处理媒体流)
在你的offscreen.js里,要维护两个独立的录制实例和数据缓存:
// 初始化两个录制器和缓存数组 let speakerRecorder = null; let micRecorder = null; let speakerAudioChunks = []; let micAudioChunks = []; // 监听Popup发来的消息 chrome.runtime.onMessage.addListener(async (msg, sender, sendResp) => { if (msg.action === "start-recording") { // 1. 捕获标签页扬声器音频 try { const tabAudioStream = await chrome.tabCapture.capture({ audio: true, video: false, audioConstraints: { // 关闭回声消除和降噪,避免影响原始音频 echoCancellation: false, noiseSuppression: false, autoGainControl: false } }); // 初始化扬声器录制器 speakerRecorder = new MediaRecorder(tabAudioStream, { mimeType: "audio/wav" }); speakerRecorder.ondataavailable = (e) => { if (e.data.size > 0) speakerAudioChunks.push(e.data); }; speakerRecorder.onstop = () => { // 生成扬声器音频Blob,发给Popup下载 const speakerBlob = new Blob(speakerAudioChunks, { type: "audio/wav" }); chrome.runtime.sendMessage({ action: "download-speaker", blob: speakerBlob }); speakerAudioChunks = []; // 清空缓存 }; speakerRecorder.start(); } catch (err) { console.error("捕获标签页音频失败:", err); } // 2. 捕获本地麦克风音频 try { const micAudioStream = await navigator.mediaDevices.getUserMedia({ audio: true }); // 初始化麦克风录制器 micRecorder = new MediaRecorder(micAudioStream, { mimeType: "audio/wav" }); micRecorder.ondataavailable = (e) => { if (e.data.size > 0) micAudioChunks.push(e.data); }; micRecorder.onstop = () => { // 生成麦克风音频Blob,发给Popup下载 const micBlob = new Blob(micAudioChunks, { type: "audio/wav" }); chrome.runtime.sendMessage({ action: "download-mic", blob: micBlob }); micAudioChunks = []; // 清空缓存 }; micRecorder.start(); } catch (err) { console.error("捕获麦克风音频失败:", err); } } else if (msg.action === "stop-recording") { // 停止两个录制器并释放流资源 if (speakerRecorder && speakerRecorder.state !== "inactive") { speakerRecorder.stop(); speakerRecorder.stream.getTracks().forEach(track => track.stop()); } if (micRecorder && micRecorder.state !== "inactive") { micRecorder.stop(); micRecorder.stream.getTracks().forEach(track => track.stop()); } } });
第三步:修改Popup的下载逻辑
在你的popup.js里,要监听Offscreen发来的Blob数据,分别触发下载:
chrome.runtime.onMessage.addListener((msg, sender, sendResp) => { // 处理扬声器音频下载 if (msg.action === "download-speaker") { const url = URL.createObjectURL(msg.blob); const downloadLink = document.createElement("a"); downloadLink.href = url; downloadLink.download = "speaker.wav"; downloadLink.click(); URL.revokeObjectURL(url); // 释放资源 } // 处理麦克风音频下载 else if (msg.action === "download-mic") { const url = URL.createObjectURL(msg.blob); const downloadLink = document.createElement("a"); downloadLink.href = url; downloadLink.download = "mic.wav"; downloadLink.click(); URL.revokeObjectURL(url); } });
第四步:添加权限请求逻辑
第一次使用时,用户需要授予扩展捕获音频的权限,所以在Popup的开始录制按钮点击事件里,要先检查并请求权限:
async function requestNecessaryPermissions() { const requiredPermissions = { permissions: ["tabCapture", "audioCapture"] }; const isGranted = await chrome.permissions.request(requiredPermissions); if (!isGranted) { alert("必须授予音频捕获权限才能进行录制哦"); return false; } return true; } // 绑定到开始录制按钮的点击事件 document.getElementById("start-btn").addEventListener("click", async () => { const hasPermissions = await requestNecessaryPermissions(); if (!hasPermissions) return; // 确保Offscreen文档已打开 await chrome.offscreen.createDocument({ url: "offscreen.html", reasons: ["AUDIO_CAPTURE"], justification: "录制标签页和麦克风音频" }); // 发送开始录制消息给Offscreen chrome.runtime.sendMessage({ action: "start-recording" }); // 这里可以更新图标为录制中状态 });
额外注意点
- 音频格式兼容:如果你的Chrome版本不支持
audio/wav作为MediaRecorder的MIME类型,可以先用audio/webm录制,之后再转成WAV格式(需要额外写转码逻辑,比如用AudioContext提取原始PCM数据,再拼接WAV文件头) - Offscreen文档生命周期:录制过程中不要关闭Popup,否则Offscreen文档可能会被销毁,导致录制中断
- Google Meet的特殊情况:tabCapture捕获的是标签页的输出音频,也就是Meet里混合后的所有声音(包括其他参与者和系统提示音),而getUserMedia捕获的是你本地麦克风的原始输入,完全分开,符合你的需求
备注:内容来源于stack exchange,提问作者Deshwal
相关产品推荐
相关产品推荐

