You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Chrome Extension捕获并流式传输Google Meet的实时音频?

如何通过Chrome Extension捕获并流式传输Google Meet的实时音频?

嘿,我之前做过类似的Chrome扩展来处理Google Meet的音频流,给你分享几个可行的方案和实际开发中踩过的坑:

方案一:用getDisplayMedia捕获桌面级Meet音频

这个方法最直接,适合需要捕获整个Meet会议所有声音的场景:

  • 首先得在扩展的manifest.json里申请必要权限:"desktopCapture"、"activeTab"、"scripting",确保扩展能获取当前页面权限和桌面音频捕获权限。
  • 在内容脚本或弹出页里调用API获取音频流:
async function getMeetAudioStream() {
  try {
    // 只请求音频捕获,不需要视频,优先捕获当前标签页音频减少杂音
    const stream = await navigator.mediaDevices.getDisplayMedia({
      audio: true,
      video: false,
      preferCurrentTab: true
    });
    return stream;
  } catch (err) {
    console.error("捕获音频失败:", err);
  }
}
  • 注意:用户需要手动授权音频捕获,要是同时开了其他应用的声音会被一起录进去,但专注Meet会议的话影响不大。

方案二:直接从Meet的Web Audio上下文提取纯净音频

这个方法能精准只捕获Meet页面的音频,不会混入其他桌面声音:

  • 因为Google Meet内部用Web Audio API处理音频,我们可以注入脚本到Meet页面,找到它的音频源节点并导出流:
// 注入到Meet页面的脚本
function extractMeetAudio() {
  // 兼容不同浏览器的AudioContext
  const AudioCtx = window.AudioContext || window.webkitAudioContext;
  // 找到页面里的audio/video元素,这些是Meet的音频载体
  const mediaElements = document.querySelectorAll('audio, video');
  if (!mediaElements.length) return null;

  const audioContext = new AudioCtx();
  const destination = audioContext.createMediaStreamDestination();

  // 把所有媒体元素的音频源连接到目标节点
  mediaElements.forEach(el => {
    const source = audioContext.createMediaElementSource(el);
    source.connect(destination);
  });

  // 拿到纯净的Meet音频流
  return destination.stream;
}
  • 注意:Meet的页面结构和音频处理逻辑可能会更新,需要定期测试适配;另外要确保脚本在Meet页面完全加载后再执行,可以用chrome.scripting.executeScript指定world: 'MAIN'注入到页面主线程。

方案三:用AudioWorklet做实时处理+流式传输(就是你提到的方向)

如果需要对音频做实时处理(比如降噪、编码)再传输,AudioWorklet是最佳选择:

  1. 主线程代码(内容脚本或注入脚本):
async function setupAudioWorklet(audioStream) {
  const audioContext = new AudioContext();
  // 先激活AudioContext(Chrome要求用户交互后才能激活)
  await audioContext.resume();
  
  // 加载自定义的Worklet处理器文件(要放在扩展资源里,manifest要配置可访问)
  await audioContext.audioWorklet.addModule(chrome.runtime.getURL('audio-processor.js'));
  
  // 创建音频源节点和Worklet节点
  const source = audioContext.createMediaStreamSource(audioStream);
  const processorNode = new AudioWorkletNode(audioContext, 'meet-audio-processor');
  
  // 连接节点链路
  source.connect(processorNode);
  processorNode.connect(audioContext.destination);
  
  // 接收Worklet传来的处理后音频数据,通过WebSocket发送到后端
  processorNode.port.onmessage = (event) => {
    const audioChunk = event.data;
    // 假设ws是已经建立好的WebSocket连接
    ws.send(audioChunk);
  };
}
  1. AudioWorklet处理器文件(audio-processor.js):
class MeetAudioProcessor extends AudioWorkletProcessor {
  process(inputs, outputs, parameters) {
    // 取第一个输入通道的音频数据
    const inputBuffer = inputs[0][0];
    if (inputBuffer) {
      // 把Float32Array转换成Uint8Array方便传输,或者直接发送原始数据
      const data = new Uint8Array(inputBuffer.buffer);
      this.port.postMessage(data);
    }
    return true;
  }
}

registerProcessor('meet-audio-processor', MeetAudioProcessor);
  • 注意:要在manifest.json里把audio-processor.js配置为可访问资源:
"web_accessible_resources": [
  {
    "resources": ["audio-processor.js"],
    "matches": ["https://meet.google.com/*"]
  }
]

流式传输的关键注意事项

  • WebSocket连接要做好重连逻辑,比如断开后自动重试,避免会议中途断流;
  • 音频数据可以选择编码成Opus等高效格式再传输,减少带宽占用,后端对应解码即可;
  • 要处理AudioContext的悬浮状态,必须在用户有交互(比如点击扩展图标)后再激活,不然Chrome会阻止音频捕获。

Manifest配置要点

别忘了在manifest.json里配置必要的权限和匹配规则:

{
  "name": "Meet Audio Capture",
  "version": "1.0",
  "permissions": ["activeTab", "scripting", "desktopCapture"],
  "content_scripts": [
    {
      "matches": ["https://meet.google.com/*"],
      "js": ["content-script.js"]
    }
  ],
  "web_accessible_resources": [
    {
      "resources": ["audio-processor.js"],
      "matches": ["https://meet.google.com/*"]
    }
  ]
}

备注:内容来源于stack exchange,提问作者Meeting Bot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 17:09:44