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

如何修改Chrome扩展代码同时捕获标签页音视频与麦克风输入

如何在Chrome扩展中同时录制标签页音视频和麦克风输入

问题背景

我正在为学校项目开发一款Chrome扩展,用于捕获会议的音视频内容。目前参考了Chrome官方的屏幕捕获相关代码,但核心问题是当前仅能录制标签页音频,无法捕获用户麦克风输入。已通过option.js获取了麦克风权限,需要修改代码实现同时捕获两者的功能。

修改方案

要实现同时录制标签页音视频和麦克风输入,需要分别获取标签页流和麦克风流,再将两个音频轨道合并,最终录制合并后的MediaStream。以下是各文件的修改代码:

1. Service Worker代码(仅调整注释说明)

chrome.action.onClicked.addListener(async (tab) => {
  const existingContexts = await chrome.runtime.getContexts({});

  const offscreenDocument = existingContexts.find(
    (c) => c.contextType === 'OFFSCREEN_DOCUMENT'
  );

  // 如果未打开离屏文档,创建一个
  if (!offscreenDocument) {
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: ['USER_MEDIA'],
      justification: '同时录制标签页音视频与麦克风输入',
    });
  }

  // 获取当前标签页的媒体流ID
  const streamId = await chrome.tabCapture.getMediaStreamId({
    targetTabId: tab.id
  });

  // 将流ID发送到离屏文档,启动录制流程
  chrome.runtime.sendMessage({
    type: 'start-recording',
    target: 'offscreen',
    data: streamId
  });
});

2. Offscreen Document代码(核心修改:合并双音频流)

这里需要先获取标签页的音视频流,再获取麦克风音频流,然后将两者的音频轨道合并到同一个MediaStream中,最后使用MediaRecorder进行录制:

chrome.runtime.onMessage.addListener(async (message) => {
  if (message.target !== 'offscreen') return;
  
  if (message.type === 'start-recording') {
    try {
      // 1. 获取标签页的音视频流
      const tabStream = await navigator.mediaDevices.getUserMedia({
        audio: {
          mandatory: {
            chromeMediaSource: "tab",
            chromeMediaSourceId: message.data,
          },
        },
        video: {
          mandatory: {
            chromeMediaSource: "tab",
            chromeMediaSourceId: message.data,
          },
        },
      });

      // 2. 获取麦克风音频流(已通过option.js获取权限)
      const micStream = await navigator.mediaDevices.getUserMedia({
        audio: true,
        video: false
      });

      // 3. 合并两个音频轨道到标签页流中
      const micAudioTrack = micStream.getAudioTracks()[0];
      tabStream.addTrack(micAudioTrack);

      // 播放合并后的音频给用户(可选)
      const output = new AudioContext();
      const source = output.createMediaStreamSource(tabStream);
      source.connect(output.destination);

      // 4. 初始化MediaRecorder开始录制
      const recorder = new MediaRecorder(tabStream, { mimeType: 'video/webm; codecs=vp9,opus' });
      const chunks = [];

      recorder.ondataavailable = (e) => chunks.push(e.data);
      recorder.onstop = () => {
        const blob = new Blob(chunks, { type: 'video/webm' });
        // 处理录制完成的Blob,示例为下载到本地
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = '会议录制_' + new Date().toISOString() + '.webm';
        a.click();
        URL.revokeObjectURL(url);
      };

      recorder.start();

      // 示例:录制10秒后自动停止(可根据需求调整)
      setTimeout(() => recorder.stop(), 10000);
    } catch (err) {
      console.error('录制启动失败:', err);
      alert('录制启动失败,请检查权限设置');
    }
  }
});

3. option.js代码(优化权限处理逻辑)

document.getElementById('requestPermission').addEventListener('click', () => {
  navigator.mediaDevices.getUserMedia({ audio: true })
    .then(stream => {
      // 获取权限后释放临时流
      stream.getTracks().forEach(track => track.stop());
      alert('麦克风权限已获取');
    })
    .catch(err => {
      alert('权限获取失败: ' + err);
    });
});

关键说明

  • 合并流时,通过addTrack方法将麦克风的音频轨道添加到标签页的MediaStream中,录制的视频会同时包含标签页和麦克风的音频。
  • 必须确保用户已授予麦克风权限(通过option.js的按钮触发),否则getUserMedia({audio: true})会执行失败。
  • 录制格式选用video/webm,这是Chrome原生支持的通用格式,兼容性较好。

内容的提问来源于stack exchange,提问作者TINTIN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 16:04:54