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

使用Puppeteer录制Google Meet音频失败问题求助

Puppeteer录制Google Meet音频为空的解决方案

问题概述

已实现通过Puppeteer以机器人身份加入Google Meet并正常录制视频,但无法捕获会议音频,尝试puppeteer-screen-recorder、puppeteer-stream等工具后,生成的音频文件均为空。

原测试代码

import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { executablePath } from 'puppeteer';
import fs from 'fs';
import AudioRecorder from 'node-audiorecorder';
import * as PuppeteerScreenRecorder from 'puppeteer-screen-recorder'
import RecordRTC from 'recordrtc';

import { getStream } from "puppeteer-stream";

const file = fs.createWriteStream("./test.webm");

puppeteer.use(StealthPlugin());
(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null,
    devtools: false,
    args: [
      "--window-size=1920,1080",
      "--window-position=1921,0",
      "--autoplay-policy=no-user-gesture-required",
    ],
    ignoreDefaultArgs: ["--mute-audio"],
    executablePath: executablePath(),
  });

  const page = await browser.newPage();
  const navigationPromise = page.waitForNavigation();
  const context = browser.defaultBrowserContext();

  await context.overridePermissions(
    "https://meet.google.com/", ["microphone", "camera", "notifications"]
  );

  await page.waitForTimeout(2500);
  await page.goto('https://meet.google.com/cmp-zzwo-adb' + '?hl=en', {
    waitUntil: 'networkidle0',
    timeout: 10000,
  });

  await navigationPromise;

  await page.waitForSelector('input[aria-label="Your name"]', {
    visible: true,
    timeout: 50000,
    hidden: false,
  });

  await page.waitForTimeout(1000);
  await page.keyboard.down('ControlLeft');
  await page.keyboard.press('KeyE');
  await page.keyboard.up('ControlLeft');
  await page.waitForTimeout(1000);

  await page.waitForTimeout(1000);
  await page.keyboard.down('ControlLeft');
  await page.keyboard.press('KeyD');
  await page.keyboard.up('ControlLeft');
  await page.waitForTimeout(1000);

  await page.click(`input[aria-label="Your name"]`);
  await page.type(`input[aria-label="Your name"]`, 'Bot');

  await page.click(
    `button[class="VfPpkd-LgbsSe VfPpkd-LgbsSe-OWXEXe-k8QpJ VfPpkd-LgbsSe-OWXEXe-dgl2Hf nCP5yc AjY5Oe DuMIQc LQeN7 jEvJdc QJgqC"]`
  );

  const stream = await getStream(page, { audio: true, mimeType: "audio/mp3" });
  console.log("recording");

  stream.pipe(file);

  const recorder = new PuppeteerScreenRecorder.PuppeteerScreenRecorder(page);
  await recorder.start('./report/video/simple.webm');

  setTimeout(async () => {
    await recorder.stop();
    await stream.destroy();
    file.close();
    console.log("finished");
    await browser.close();
  }, 15000)

})();

原package.json

{
  "name": "own",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "node-audiorecorder": "^3.0.0",
    "puppeteer": "^19.6.3",
    "puppeteer-extra": "^3.3.4",
    "puppeteer-extra-plugin-stealth": "^2.11.1",
    "puppeteer-screen-recorder": "^2.1.2",
    "puppeteer-stream": "^2.1.4",
    "recordrtc": "^5.6.2",
    "screencap": "^1.0.0",
    "ws": "^8.12.1"
  }
}

问题原因分析

  1. 多录制工具冲突:同时使用puppeteer-stream和PuppeteerScreenRecorder抢占音频资源,导致捕获失败
  2. 权限与参数缺失:未添加WebRTC音频捕获所需的浏览器启动参数,无法正确识别Meet的媒体流
  3. 选择器不稳定:使用Google Meet动态生成的class选择器,易因UI更新导致操作失效
  4. 音频捕获逻辑错误:普通页面音频捕获无法直接获取WebRTC传输的Meet会议音频

解决方案

1. 精简录制逻辑,避免资源冲突

移除重复的puppeteer-stream录制代码,仅保留PuppeteerScreenRecorder并配置音频参数

2. 添加必要的浏览器启动参数

补充WebRTC媒体流捕获所需的参数,绕过设备权限弹窗

3. 替换不稳定选择器

使用aria-label替代动态class选择器,保证脚本稳定性

修改后的完整代码

import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { executablePath } from 'puppeteer';
import * as PuppeteerScreenRecorder from 'puppeteer-screen-recorder'

puppeteer.use(StealthPlugin());
(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null,
    devtools: false,
    args: [
      "--window-size=1920,1080",
      "--window-position=1921,0",
      "--autoplay-policy=no-user-gesture-required",
      "--use-fake-ui-for-media-stream",
      "--use-fake-device-for-media-stream",
      "--enable-usermedia-screen-capturing",
      "--allow-file-access-from-files"
    ],
    ignoreDefaultArgs: ["--mute-audio"],
    executablePath: executablePath(),
  });

  const page = await browser.newPage();
  const context = browser.defaultBrowserContext();

  await context.overridePermissions(
    "https://meet.google.com/", ["microphone", "camera", "notifications"]
  );

  await page.goto('https://meet.google.com/cmp-zzwo-adb?hl=en', {
    waitUntil: 'networkidle0',
    timeout: 10000,
  });

  await page.waitForSelector('input[aria-label="Your name"]', {
    visible: true,
    timeout: 50000,
  });

  // 关闭摄像头
  await page.keyboard.down('ControlLeft');
  await page.keyboard.press('KeyE');
  await page.keyboard.up('ControlLeft');
  await page.waitForTimeout(1000);

  // 关闭麦克风
  await page.keyboard.down('ControlLeft');
  await page.keyboard.press('KeyD');
  await page.keyboard.up('ControlLeft');
  await page.waitForTimeout(1000);

  // 输入名称并加入会议
  await page.click(`input[aria-label="Your name"]`);
  await page.type(`input[aria-label="Your name"]`, 'Bot');
  await page.click(`button[aria-label="Ask to join"]`);

  // 等待会议加载完成
  await page.waitForTimeout(5000);

  // 配置带音频的屏幕录制
  const recorder = new PuppeteerScreenRecorder.PuppeteerScreenRecorder(page, {
    audio: {
      codec: 'opus',
      bitrate: 128000
    },
    video: {
      codec: 'vp8',
      bitrate: 2500000
    },
    fps: 30
  });
  await recorder.start('./report/video/meet-recording.webm');

  // 录制15秒后停止
  setTimeout(async () => {
    await recorder.stop();
    console.log("录制完成");
    await browser.close();
  }, 15000);

})();

关键修改说明

  • 添加--use-fake-ui-for-media-stream等参数,绕过真实设备权限验证,直接捕获WebRTC流
  • 配置PuppeteerScreenRecorder的音频编码参数,明确指定opus编码确保音频正常捕获
  • 用aria-label="Ask to join"替代动态class选择器,避免UI更新导致按钮点击失效
  • 移除冲突的puppeteer-stream逻辑,确保单一录制工具独占音频资源

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:39:21