基于SpeechRecognition的语音助手:区分用户指令与主动静默需求
区分语音助手的用户静默与识别失败场景解决方案
一、基于音频分贝阈值的并行实现方案
核心思路
通过多线程并行执行两个任务:
- 线程1:实时采集音频并计算音量(RMS均方根值),判断是否处于持续静默状态
- 线程2:执行原有
takeCommand函数进行语音识别
共享一个状态标记,当线程1检测到用户主动静默时,触发标记,线程2识别失败后优先判断该标记,决定返回main函数还是提示重说。
代码实现
- 安装依赖:
pip install SpeechRecognition sounddevice numpy
- 完整代码示例:
import speech_recognition as sr import sounddevice as sd import numpy as np import threading import time # 全局标记:是否检测到静默 silence_detected = False # 静默阈值(可根据环境调整,RMS值越小越安静) SILENCE_THRESHOLD = 0.001 # 持续静默判定时长(秒) SILENCE_DURATION = 3 def detect_silence(): global silence_detected silence_start = None def audio_callback(indata, frames, time, status): nonlocal silence_start # 计算当前音频帧的RMS值 rms = np.sqrt(np.mean(indata**2)) if rms < SILENCE_THRESHOLD: if silence_start is None: silence_start = time.time() elif time.time() - silence_start >= SILENCE_DURATION: silence_detected = True else: silence_start = None silence_detected = False # 启动音频监听流 with sd.InputStream(callback=audio_callback): while True: if silence_detected: break time.sleep(0.1) def takeCommand(): r = sr.Recognizer() with sr.Microphone() as source: print("请说话...") r.adjust_for_ambient_noise(source, duration=0.5) audio = r.listen(source) try: print("识别中...") query = r.recognize_google(audio, language='zh-CN') print(f"你说的是: {query}") return query except sr.UnknownValueError: return None except sr.RequestError: print("语音识别服务不可用") return None def conversation(): global silence_detected while True: # 重置静默标记 silence_detected = False # 启动静默检测线程 silence_thread = threading.Thread(target=detect_silence) silence_thread.daemon = True silence_thread.start() # 执行语音识别 command = takeCommand() if command: # 处理有效指令逻辑 print(f"处理指令: {command}") if command == "退出": break else: if silence_detected: print("检测到主动静默,返回主函数") return # 返回main函数 else: print("未识别到有效指令,请重说") def main(): print("主函数启动,进入对话模式...") conversation() print("回到主函数,结束对话") if __name__ == "__main__": main()
注意事项
SILENCE_THRESHOLD和SILENCE_DURATION需要根据实际环境调整,避免误判- 线程设置为守护线程,防止程序退出时残留线程
二、AI/ML进阶方案(语音活动检测VAD)
单纯分贝阈值容易被背景噪音干扰,使用专业的**语音活动检测(VAD)**模型可以更准确区分用户主动静默和背景噪音,推荐使用webrtcvad(谷歌开源的轻量级VAD模型),无需训练即可直接使用。
核心思路
在采集音频前,先通过VAD模型判断是否存在有效语音:
- 如果VAD检测到无语音活动,直接判定为用户主动静默,返回
main函数 - 如果检测到语音活动,再执行语音识别,识别失败则提示重说
代码实现
- 安装依赖:
pip install SpeechRecognition webrtcvad pyaudio
- 关键代码片段:
import webrtcvad import speech_recognition as sr from collections import deque def has_voice_activity(audio_data, sample_rate=16000): vad = webrtcvad.Vad(3) # 模式3,最严格的检测 # 将音频转换为16kHz单声道PCM格式 pcm_data = audio_data.get_raw_data(convert_rate=sample_rate, convert_width=2) frame_duration = 30 # 每帧30毫秒 frame_size = int(sample_rate * frame_duration / 1000) # 滑动窗口检测语音活动 voice_frames = deque(maxlen=10) for i in range(0, len(pcm_data), frame_size*2): frame = pcm_data[i:i+frame_size*2] if len(frame) < frame_size*2: break is_speech = vad.is_speech(frame, sample_rate) voice_frames.append(is_speech) # 判断是否存在连续语音帧 return any(voice_frames) def takeCommandWithVAD(): r = sr.Recognizer() with sr.Microphone() as source: print("请说话...") r.adjust_for_ambient_noise(source, duration=0.5) audio = r.listen(source) # 先检测是否有语音活动 if not has_voice_activity(audio): return "silence" try: print("识别中...") query = r.recognize_google(audio, language='zh-CN') print(f"你说的是: {query}") return query except sr.UnknownValueError: return None except sr.RequestError: print("语音识别服务不可用") return None def conversation(): while True: command = takeCommandWithVAD() if command == "silence": print("检测到主动静默,返回主函数") return elif command: print(f"处理指令: {command}") if command == "退出": break else: print("未识别到有效指令,请重说")
方案优势
- 基于语音特征检测,比单纯分贝阈值准确率高
- 轻量级模型,无需额外训练,运行效率高
内容的提问来源于stack exchange,提问作者styles
相关产品推荐
相关产品推荐

