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

Python命令行个人助手“Hey Siri”热词监听优化方案咨询

嘿,这个问题我之前帮不少开发者解决过——用while循环轮询监听确实会有延迟、漏指令的问题,核心原因是每次循环都要完成一次「启动麦克风→采集固定时长音频→调用识别API」的流程,中间的间隙和固定时长限制,要么漏听热词起始点,要么频繁调用API拖慢响应速度。给你几个更优的方案,尤其是结合**语音活动检测(VAD)**的思路,完美匹配你说的「无语音时停止识别循环」的需求:

最优方案:结合语音活动检测(VAD)实现实时热词唤醒

1. 为什么你的当前方案存在缺陷?

你的while循环每次都要触发完整的识别流程,无语音时也在做无效的识别请求,既浪费资源,又因为固定采集时长的限制,很容易错过热词的起始部分(比如热词刚好在两次循环间隙开始)。

2. 核心思路:用VAD只在有语音时触发识别

语音活动检测(VAD)可以实时分析音频流,精准判断当前是否有人说话。我们可以让麦克风持续采集音频流,用VAD检测到语音后再启动热词识别逻辑;无语音时,只做音频采集和VAD检测,不调用识别API——这样既节省资源,又能保证连续监听,不会错过热词。

3. 具体实现:用webrtcvad配合speech_recognition

webrtcvad是谷歌开源的轻量级VAD库,准确率高、性能优秀,非常适合实时场景。下面是完整的可运行示例:

首先安装依赖:

pip install speechrecognition webrtcvad pyaudio

然后是核心代码:

import speech_recognition as sr
import webrtcvad
import collections
import sys

def main():
    # 初始化VAD,设置灵敏度(0-3,数值越高对噪音越严格)
    vad = webrtcvad.Vad(1)
    # VAD要求的标准音频参数:16kHz采样率、单声道、16位深度
    sample_rate = 16000
    chunk_duration_ms = 30  # VAD需要30ms的音频块作为检测单元
    chunk_size = int(sample_rate * chunk_duration_ms / 1000)

    # 初始化识别器和麦克风
    r = sr.Recognizer()
    mic = sr.Microphone(sample_rate=sample_rate)

    # 首次运行校准麦克风,降低环境噪音干扰
    print("请安静,正在校准麦克风...")
    with mic as source:
        r.adjust_for_ambient_noise(source, duration=1)
    print("校准完成,等待热词唤醒...")

    # 用队列保存音频块,方便拼接完整的语音片段
    ring_buffer = collections.deque(maxlen=20)  # 最多保存600ms的音频
    triggered = False  # 标记是否检测到连续语音

    with mic as source:
        while True:
            # 读取30ms的音频块
            audio = r.record(source, duration=chunk_duration_ms/1000)
            # 转换为VAD要求的PCM格式
            pcm_data = audio.get_raw_data(convert_rate=sample_rate, convert_width=2)
            
            # 判断当前音频块是否包含语音
            is_speech = vad.is_speech(pcm_data, sample_rate)

            if not triggered:
                ring_buffer.append((pcm_data, is_speech))
                # 连续检测到3个语音块,判定为开始说话
                num_voiced = len([chunk for chunk, speech in ring_buffer if speech])
                if num_voiced > 3:
                    triggered = True
                    print("检测到语音,准备识别热词...")
            else:
                ring_buffer.append((pcm_data, is_speech))
                # 连续10个无语音块,判定为说话结束
                num_unvoiced = len([chunk for chunk, speech in ring_buffer if not speech])
                if num_unvoiced > 10:
                    triggered = False
                    # 拼接完整的语音片段
                    full_audio = b''.join([chunk for chunk, _ in ring_buffer])
                    ring_buffer.clear()

                    # 转换为speech_recognition可处理的AudioData对象
                    audio_data = sr.AudioData(full_audio, sample_rate, 2)
                    try:
                        # 识别语音内容
                        text = r.recognize_google(audio_data, language='zh-CN')
                        print(f"识别内容: {text}")
                        # 判断是否触发热词(可根据需求调整匹配规则)
                        if "hey siri" in text.lower():
                            print("热词唤醒成功!请说出你的指令...")
                            # 这里添加后续指令处理逻辑
                            command_audio = r.listen(source)
                            command_text = r.recognize_google(command_audio)
                            print(f"你的指令: {command_text}")
                    except sr.UnknownValueError:
                        print("无法识别语音,请重试")
                    except sr.RequestError as e:
                        print(f"调用Google识别服务失败: {e}")

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n程序已退出")
        sys.exit()

4. 关键优化点说明

  • VAD灵敏度调整:如果环境噪音大,可将webrtcvad.Vad(1)的参数调至2或3;安静环境用0或1即可。
  • 语音片段拼接:用队列保存音频块,避免固定时长采集截断语音,保证完整捕获热词。
  • 噪音校准:启动时的adjust_for_ambient_noise能有效降低环境噪音对识别的干扰,建议保留。

5. 其他可选方案

如果不想自己实现VAD逻辑,也可以用现成的热词唤醒库:

  • porcupine:专门的热词唤醒工具,支持自定义热词,准确率极高,免费版可用于非商业场景。
  • snowboy:开源离线热词库,适合无网络场景,但维护活跃度不如porcupine。

不过结合webrtcvad的方案完全免费开源,适配你的命令行助手场景最划算。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:01:22