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

Python语音聊天机器人音频路由问题:如何避免识别自身播放音频?

问题描述

我开发了一个具备音频播放与录制功能的Python语音交互聊天机器人,通过线程同时运行播放与录制代码:

import os
import soundfile as sf
import sounddevice as sd
import speech_recognition as sr

def play_audio(file_name):
    audio_path = os.path.join(path, file_name)
    data, fs = sf.read(audio_path)
    sd.play(data, fs)
    sd.wait()

def rec_audio():
    recog = sr.Recognizer()

    with sr.Microphone() as source:
        print("Listening... From Site Rec..")
        audio = recog.listen(source)

    data = ""

    try:
        data = recog.recognize_google(audio)
        print("User: " + data)

    except sr.UnknownValueError:
        print("Machine coudn't process..")
        play_audio("voice break.mp3")
    except sr.RequestError as ex:
        print("Google side" + str(ex))
        play_audio("RequestError.mp3")

    return data

目前机器人会将自身的音频输出识别为输入,需要解决:

  • 如何阻止这种自识别情况
  • 是否有应用间音频路由工具可用
  • 怎么设置让机器人仅识别麦克风输入,排除自身播放音频
解决方案

一、代码层面优化(无需额外工具)

1. 播放时暂停录制线程

多线程场景下,直接在播放前暂停录制逻辑,播放完成后恢复,用threading.Event做信号控制:

import threading

# 全局事件控制录制启停
recording_active = threading.Event()
recording_active.set()  # 默认允许录制

def rec_audio():
    recog = sr.Recognizer()
    with sr.Microphone() as source:
        while True:
            recording_active.wait()  # 等待允许录制的信号
            print("Listening... From Site Rec..")
            audio = recog.listen(source)
            
            data = ""
            try:
                data = recog.recognize_google(audio)
                print("User: " + data)
            except sr.UnknownValueError:
                print("Machine coudn't process..")
                play_audio("voice break.mp3")
            except sr.RequestError as ex:
                print("Google side" + str(ex))
                play_audio("RequestError.mp3")
            return data

def play_audio(file_name):
    recording_active.clear()  # 播放前暂停录制
    audio_path = os.path.join(path, file_name)
    data, fs = sf.read(audio_path)
    sd.play(data, fs)
    sd.wait()
    recording_active.set()  # 播放完成恢复录制

2. 用语音活动检测(VAD)过滤无效音频

借助webrtcvad库过滤掉低音量或非人声的播放音频,先安装库:pip install webrtcvad,修改录制逻辑:

import webrtcvad

def rec_audio():
    recog = sr.Recognizer()
    vad = webrtcvad.Vad(3)  # 3为最严格检测模式,可根据需求调1-3
    with sr.Microphone() as source:
        print("Listening... From Site Rec..")
        audio = recog.listen(source)
        
        # 转换音频格式适配VAD要求(16kHz采样率、16位宽度)
        raw_audio = audio.get_raw_data(convert_rate=16000, convert_width=2)
        frame_duration = 30  # VAD要求的帧时长,固定30ms
        frame_size = int(16000 * frame_duration / 1000) * 2  # 每帧字节数
        frames = [raw_audio[i:i+frame_size] for i in range(0, len(raw_audio), frame_size)]
        
        # 检测是否包含有效人声
        has_valid_speech = any(vad.is_speech(frame, 16000) for frame in frames)
        if not has_valid_speech:
            return ""  # 无有效人声直接返回空
        
        data = ""
        try:
            data = recog.recognize_google(audio)
            print("User: " + data)
        except sr.UnknownValueError:
            print("Machine coudn't process..")
            play_audio("voice break.mp3")
        except sr.RequestError as ex:
            print("Google side" + str(ex))
            play_audio("RequestError.mp3")
        return data

二、系统级音频路由工具

如果不想修改代码,可通过系统工具隔离输入输出:

  • Windows:使用VoiceMeeter,将机器人播放输出设置到虚拟音频设备,录制时指定物理麦克风:
    1. 安装VoiceMeeter后,在系统声音设置中将默认播放设备设为VoiceMeeter虚拟输出;
    2. 在VoiceMeeter界面,把物理麦克风设为输入,实际扬声器设为输出;
    3. 代码中指定麦克风设备:sr.Microphone(device_index=你的麦克风索引),可用sr.Microphone.list_microphone_names()查看所有设备索引。
  • macOS:使用BlackHole或Soundflower创建虚拟音频设备,将机器人播放路由到虚拟设备,录制时选择物理麦克风即可。
  • Linux:使用pavucontrol(PulseAudio音量控制),在「录制」选项卡中,将机器人的录制来源强制设置为物理麦克风,而非「Monitor of 扬声器」。

三、硬件层面隔离

最省心的方式是用带监听屏蔽功能的麦克风,或者用耳机播放机器人音频,避免扬声器声音回传到麦克风。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:05:37