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

如何使用Selenium Python录制Google会议并上传至服务器

解决Google Meet自动化录制问题

核心问题分析

你的代码存在几个关键问题导致录制无法启动:

  • 仅定义了startRecording异步函数,但从未调用执行
  • getDisplayMedia的权限授权在自动化环境下需要额外配置,默认会被浏览器拦截
  • 依赖window.prompt会在无头/自动化环境下卡住流程
  • 直接捕获麦克风音频无法正确获取Meet会议的共享音频(应该捕获标签页/桌面的音频流)

解决方案步骤

1. 添加必要的Chrome启动参数

为了自动授予媒体权限并跳过手动选择捕获源,更新ChromeOptions:

opt = uc.ChromeOptions()
opt.add_argument('--disable-blink-features=AutomationControlled')
opt.add_argument('--start-maximized')
opt.add_argument('--disable-gpu')
# 自动授予媒体流权限,跳过手动弹窗
opt.add_argument('--use-fake-ui-for-media-stream')
# 指定捕获源为Google Meet标签页(桌面录制可改为"Entire screen")
opt.add_argument('--auto-select-desktop-capture-source=Google Meet')
# 用虚拟设备替代真实麦克风,避免权限问题
opt.add_argument('--use-fake-device-for-media-stream')

opt.add_experimental_option("prefs", {
    "profile.default_content_setting_values.media_stream_mic": 1,
    "profile.default_content_setting_values.media_stream_camera": 1,
    "profile.default_content_setting_values.geolocation": 0,
    "profile.default_content_setting_values.notifications": 1,
    # 配置自动下载路径,关闭下载弹窗
    "download.default_directory": "/path/to/your/download/folder",
    "download.prompt_for_download": False,
    "download.directory_upgrade": True
})

2. 修改录制脚本,修复执行逻辑

  • 调用startRecording函数,处理异步执行
  • 移除window.prompt,使用时间戳命名文件避免冲突
  • 优化音频捕获逻辑,优先捕获桌面/标签页的音频而非麦克风
recording_script = """
var blob, mediaRecorder = null;
var chunks = [];

async function startRecording(){
    // 捕获屏幕+标签页音频,关闭音频降噪避免失真
    let stream = await navigator.mediaDevices.getDisplayMedia({
        video: {mediaSource: "screen"},
        audio: {
            echoCancellation: false,
            noiseSuppression: false,
            autoGainControl: false
        }
    });

    mediaRecorder = new MediaRecorder(stream, {mimeType: "video/webm"});
    mediaRecorder.ondataavailable = (e) => {
        if(e.data.size > 0){
            chunks.push(e.data);
        }
    };
    mediaRecorder.onstop = () => {
        blob = new Blob(chunks, {type: "video/webm"});
        chunks = [];
        var dataDownloadUrl = URL.createObjectURL(blob);

        // 自动下载到指定目录,无弹窗
        let a = document.createElement('a');
        a.href = dataDownloadUrl;
        a.download = `meet_recording_${Date.now()}.webm`;
        a.click();

        URL.revokeObjectURL(dataDownloadUrl);
    };
    mediaRecorder.start(250);
}

// 立即启动录制,捕获启动失败的错误
startRecording().catch(err => console.error("录制启动失败:", err));
"""

3. 确保Meet账号有录制权限

Google Meet仅允许会议主持人或被授予录制权限的成员启动录制,所以你的机器人账号需要:

  • 是会议创建者,或被主持人手动授予录制权限
  • 使用Google Workspace账号(免费个人账号的录制功能有场景限制)

4. 处理录制文件上传到服务器

录制完成后,通过Python监听下载目录,找到最新录制文件并上传到服务器:

import os
import requests

# 配置下载目录和服务器上传地址
download_dir = "/path/to/your/download/folder"
upload_url = "https://your-server.com/upload-endpoint"

# 找到最新生成的webm录制文件
latest_file = max(
    [os.path.join(download_dir, f) for f in os.listdir(download_dir) if f.endswith('.webm')],
    key=os.path.getctime
)

# 上传文件到服务器
with open(latest_file, 'rb') as f:
    response = requests.post(upload_url, files={'file': f})
    if response.status_code == 200:
        print("文件上传成功")
    else:
        print(f"上传失败,状态码: {response.status_code}")

5. 完整修改后的代码

import undetected_chromedriver as uc
from selenium.webdriver.common.by import By
import time
import os
import requests

recording_script = """
var blob, mediaRecorder = null;
var chunks = [];

async function startRecording(){
    let stream = await navigator.mediaDevices.getDisplayMedia({
        video: {mediaSource: "screen"},
        audio: {
            echoCancellation: false,
            noiseSuppression: false,
            autoGainControl: false
        }
    });

    mediaRecorder = new MediaRecorder(stream, {mimeType: "video/webm"});
    mediaRecorder.ondataavailable = (e) => {
        if(e.data.size > 0){
            chunks.push(e.data);
        }
    };
    mediaRecorder.onstop = () => {
        blob = new Blob(chunks, {type: "video/webm"});
        chunks = [];
        var dataDownloadUrl = URL.createObjectURL(blob);

        let a = document.createElement('a');
        a.href = dataDownloadUrl;
        a.download = `meet_recording_${Date.now()}.webm`;
        a.click();

        URL.revokeObjectURL(dataDownloadUrl);
    };
    mediaRecorder.start(250);
}

startRecording().catch(err => console.error("录制启动失败:", err));
"""

# 初始化下载目录
download_dir = "/path/to/your/download/folder"
os.makedirs(download_dir, exist_ok=True)

# 配置Chrome选项
opt = uc.ChromeOptions()
opt.add_argument('--disable-blink-features=AutomationControlled')
opt.add_argument('--start-maximized')
opt.add_argument('--disable-gpu')
opt.add_argument('--use-fake-ui-for-media-stream')
opt.add_argument('--auto-select-desktop-capture-source=Google Meet')
opt.add_argument('--use-fake-device-for-media-stream')

opt.add_experimental_option("prefs", {
    "profile.default_content_setting_values.media_stream_mic": 1,
    "profile.default_content_setting_values.media_stream_camera": 1,
    "profile.default_content_setting_values.geolocation": 0,
    "profile.default_content_setting_values.notifications": 1,
    "download.default_directory": download_dir,
    "download.prompt_for_download": False,
    "download.directory_upgrade": True
})

# 启动浏览器并加入会议
driver = uc.Chrome(options=opt)
driver.get("meeting_url")
driver.implicitly_wait(15)

# 输入机器人名称
driver.find_element(By.XPATH,"/html/body/div/c-wiz/div/div/div[27]/div[3]/div/div[2]/div[4]/div/div/div[2]/div[1]/div[1]/div[3]/label/input").send_keys("test_bot")

# 发送加入请求
driver.find_element(By.XPATH,"/html/body/div/c-wiz/div/div/div[27]/div[3]/div/div[2]/div[4]/div/div/div[2]/div[1]/div[2]/div[1]/div[1]/button").click()

# 等待会议加载完成
time.sleep(10)
# 执行录制脚本
driver.execute_script(recording_script)

# 模拟录制时长(示例为30秒,可根据需求调整)
time.sleep(30)
# 停止录制
driver.execute_script("if(mediaRecorder) mediaRecorder.stop();")

# 等待文件下载完成
time.sleep(5)

# 上传文件到服务器
try:
    latest_file = max(
        [os.path.join(download_dir, f) for f in os.listdir(download_dir) if f.endswith('.webm')],
        key=os.path.getctime
    )
    upload_url = "https://your-server.com/upload-endpoint"
    with open(latest_file, 'rb') as f:
        res = requests.post(upload_url, files={'file': f})
        print(f"上传结果: {res.status_code} - {res.text}")
except Exception as e:
    print(f"上传失败: {str(e)}")

# 关闭浏览器
driver.quit()

额外注意事项

  • XPATH定位器不稳定,Google Meet的DOM结构经常更新,建议改用By.CSS_SELECTOR或基于aria-label等稳定属性定位元素
  • 无头模式下屏幕捕获需要额外配置,建议先在有头模式下完成功能验证
  • 长时间录制需考虑内存占用,可调整MediaRecorder.start()的时间间隔参数,或增加chunk清理逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:27:03