一、Snowboy 简介

Snowboy 是一个开源的、轻量级的语音唤醒引擎,专为嵌入式设备和移动设备设计。它允许用户通过自定义的唤醒词来激活语音助手。

主要特性:

  • 轻量高效:CPU 和内存占用小
  • 跨平台:支持 Linux、Mac、Windows、iOS、Android、Raspberry Pi
  • 离线工作:无需网络连接,保护隐私
  • 多语言支持:支持中文、英文等多种语言
  • 自定义唤醒词:用户可以训练自己的唤醒词模型

二、安装指南

1. 系统要求

  • Python 2.7 或 3.4+
  • macOS/Linux/Windows
  • Raspberry Pi(ARM 架构)也支持

2. 安装步骤

# 使用 pip 安装(推荐)
pip install snowboy

# 或者从源码安装
git clone https://github.com/Kitt-AI/snowboy.git
cd snowboy/swig/Python3
make

3. 安装依赖

# 安装必要的音频处理库
pip install pyaudio  # 用于音频输入
pip install sounddevice  # 替代方案
pip install scipy  # 音频处理
pip install numpy  # 数值计算

注意:Windows 用户安装 PyAudio 可能需要先安装 PortAudio:

# Windows 用户可以使用预编译的 PyAudio
pip install pipwin
pipwin install pyaudio

三、Python 集成开发

1. 基本使用示例

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import snowboydecoder
import sys
import signal

interrupted = False

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

def interrupt_callback():
    global interrupted
    return interrupted

# 回调函数:检测到唤醒词时执行
def detected_callback():
    print("唤醒词被检测到!")
    # 在这里添加唤醒后的处理逻辑

# 主程序
if __name__ == '__main__':
    # 捕获中断信号
    signal.signal(signal.SIGINT, signal_handler)
    
    # 模型文件路径(使用默认模型或自定义模型)
    model = "resources/snowboy.umdl"  # 通用模型
    # model = "resources/alexa.umdl"   # Alexa 模型
    # model = ["model1.pmdl", "model2.pmdl"]  # 多个唤醒词
    
    # 创建检测器
    detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
    
    print("正在监听唤醒词... 按 Ctrl+C 退出")
    
    # 开始检测
    detector.start(detected_callback=detected_callback,
                   interrupt_check=interrupt_callback,
                   sleep_time=0.03)
    
    # 清理
    detector.terminate()

2. 完整应用示例(带语音反馈)

import snowboydecoder
import sys
import signal
import os
import pygame
import threading

class VoiceAssistant:
    def __init__(self, model_path):
        self.model = model_path
        self.detector = None
        self.interrupted = False
        self.is_listening = False
        
        # 初始化音频播放(可选)
        try:
            pygame.mixer.init()
        except:
            print("音频播放初始化失败")
    
    def signal_handler(self, signal, frame):
        self.interrupted = True
    
    def play_audio(self, audio_file):
        """播放音频文件"""
        def play():
            try:
                pygame.mixer.music.load(audio_file)
                pygame.mixer.music.play()
                while pygame.mixer.music.get_busy():
                    pass
            except Exception as e:
                print(f"播放音频失败: {e}")
        
        thread = threading.Thread(target=play)
        thread.start()
    
    def wakeup_callback(self):
        """唤醒回调函数"""
        print("\n=== 唤醒词检测到! ===")
        
        # 播放提示音
        if os.path.exists("beep.wav"):
            self.play_audio("beep.wav")
        
        # 唤醒后的处理逻辑
        self.on_wakeup()
    
    def on_wakeup(self):
        """唤醒后的具体操作"""
        print("开始语音识别...")
        # 这里可以集成语音识别引擎(如百度、科大讯飞、Google等)
        # 示例:使用百度语音识别
        # result = self.baidu_asr()
        # self.process_command(result)
        
        # 或者直接执行命令
        self.execute_command("打开灯光")
    
    def execute_command(self, command):
        """执行命令"""
        print(f"执行命令: {command}")
        
        # 这里添加具体的命令处理逻辑
        if "打开灯光" in command:
            print("正在打开灯光...")
        elif "播放音乐" in command:
            print("正在播放音乐...")
        # 更多命令处理...
    
    def start(self):
        """启动唤醒检测"""
        # 设置信号处理
        signal.signal(signal.SIGINT, self.signal_handler)
        
        # 创建热词检测器
        self.detector = snowboydecoder.HotwordDetector(
            self.model,
            sensitivity=0.5,
            audio_gain=1.0
        )
        
        print("=" * 50)
        print("语音助手已启动")
        print(f"使用模型: {self.model}")
        print("正在监听唤醒词...")
        print("按 Ctrl+C 退出")
        print("=" * 50)
        
        # 开始检测
        self.is_listening = True
        self.detector.start(
            detected_callback=self.wakeup_callback,
            interrupt_check=lambda: self.interrupted,
            sleep_time=0.03,
            audio_recorder_callback=None,  # 可以添加录音回调
            silent_count_threshold=15,
            recording_timeout=100
        )
    
    def stop(self):
        """停止检测"""
        self.interrupted = True
        if self.detector:
            self.detector.terminate()
        print("语音助手已停止")

# 使用示例
if __name__ == '__main__':
    # 使用自定义模型
    assistant = VoiceAssistant("resources/你好小雅.pmdl")
    
    try:
        assistant.start()
    except KeyboardInterrupt:
        assistant.stop()

3. 多唤醒词支持

import snowboydecoder

def callback1():
    print("唤醒词1被检测到")

def callback2():
    print("唤醒词2被检测到")

def callback3():
    print("唤醒词3被检测到")

# 多个唤醒词模型和对应的回调函数
models = ["model1.pmdl", "model2.pmdl", "model3.pmdl"]
callbacks = [callback1, callback2, callback3]

# 创建检测器
detector = snowboydecoder.HotwordDetector(
    models,
    sensitivity=[0.5, 0.5, 0.5]  # 每个模型的敏感度
)

# 开始检测
detector.start(
    detected_callback=callbacks,
    interrupt_check=lambda: False
)

四、自定义唤醒词训练与替换

1. 在线训练(推荐)

Snowboy 提供在线训练平台,但注意:原官方训练平台已关闭,以下是替代方案:

方案一:使用 HMM 方法训练(技术要求较高)
# 1. 准备训练数据
# 需要准备3个音频文件:
# - 3次说唤醒词的录音(16kHz,单声道,wav格式)
# - 背景噪音录音
# - 非唤醒词的其他词录音

# 2. 使用开源工具训练
# 可以使用类似 Kaldi 的工具进行训练
方案二:使用替代服务

目前有一些替代的语音唤醒训练服务:

  • Porcupine(Picovoice):提供免费训练
  • Mycroft Precise:开源训练工具
  • 自定义神经网络模型:使用 TensorFlow 或 PyTorch 训练

2. 使用预训练模型

Snowboy 提供了一些预训练模型:

  • snowboy.umdl:通用英文唤醒词
  • alexa.umdl:Alexa 唤醒词
  • jarvis.umdl:Jarvis 唤醒词
  • smart_mirror.umdl:智能镜子唤醒词

3. 模型替换示例

# 不同的唤醒词模型
MODELS = {
    "snowboy": "resources/snowboy.umdl",
    "alexa": "resources/alexa.umdl", 
    "jarvis": "resources/jarvis.umdl",
    "custom": "resources/my_wake_word.pmdl"
}

def load_model(model_name):
    """动态加载唤醒词模型"""
    model_path = MODELS.get(model_name)
    if not model_path or not os.path.exists(model_path):
        print(f"模型 {model_name} 不存在,使用默认模型")
        model_path = MODELS["snowboy"]
    
    return model_path

# 使用动态模型
current_model = load_model("custom")
detector = snowboydecoder.HotwordDetector(current_model, sensitivity=0.5)

4. 自定义训练流程(使用 Mycroft Precise)

# 安装 Mycroft Precise
git clone https://github.com/MycroftAI/mycroft-precise
cd mycroft-precise
pip install -r requirements.txt
python setup.py install

# 收集训练数据
# 录制唤醒词音频(至少50个样本)
# 录制非唤醒词音频(至少200个样本)

# 训练模型
precise-train \
    wake-word.net \
    data/wake-word/ \
    data/not-wake-word/

# 转换模型为 Snowboy 格式(需要额外工具)

五、高级配置与优化

1. 参数调整

detector = snowboydecoder.HotwordDetector(
    model,
    sensitivity=0.5,      # 敏感度:0-1,值越高越敏感
    audio_gain=1.0,       # 音频增益
    apply_frontend=False   # 是否应用前端处理
)

2. 性能优化

class OptimizedDetector:
    def __init__(self):
        # 使用更低的采样率
        self.DETECTION_SAMPLE_RATE = 16000
        
        # 调整检测参数
        self.config = {
            "APPLY_FRONTEND": True,
            "SENSITIVITY": 0.4,
            "SILENCE_LIMIT": 2,  # 静音时间限制
            "SPEECH_TIMEOUT": 30  # 语音超时
        }
    
    def energy_vad(self, audio_data):
        """基于能量的语音活动检测"""
        import numpy as np
        energy = np.sum(audio_data ** 2) / len(audio_data)
        return energy > 0.01  # 阈值

3. 集成其他语音服务

class IntegratedAssistant:
    def __init__(self):
        # 初始化 Snowboy
        self.snowboy_detector = snowboydecoder.HotwordDetector("model.pmdl")
        
        # 初始化其他服务
        # self.asr_service = ASRService()  # 语音识别
        # self.tts_service = TTSService()  # 语音合成
        # self.nlp_service = NLPService()  # 自然语言处理
    
    def full_pipeline(self):
        """完整处理流程"""
        # 1. 唤醒词检测
        # 2. 语音识别
        # 3. 自然语言理解
        # 4. 执行命令
        # 5. 语音反馈
        pass

六、常见问题与解决方案

1. 安装问题

# PyAudio 安装失败
# Ubuntu/Debian
sudo apt-get install portaudio19-dev python-pyaudio

# macOS
brew install portaudio
pip install pyaudio

# Windows
pip install pipwin
pipwin install pyaudio

2. 性能问题

# 降低 CPU 使用率
detector.start(sleep_time=0.05)  # 增加休眠时间

# 使用更简单的模型
# 减少唤醒词长度
# 调整敏感度

3. 准确率问题

# 调整敏感度
sensitivities = [0.4, 0.45, 0.5, 0.55, 0.6]

# 使用音频预处理
def preprocess_audio(audio_data):
    # 降噪、增益控制等
    return processed_audio

七、注意事项

  1. 模型训练:原官方训练平台已关闭,需要寻找替代方案
  2. 实时性:Snowboy 对实时性要求较高,确保系统延迟低
  3. 背景噪音:在嘈杂环境下效果可能下降
  4. 多唤醒词:同时使用多个唤醒词会增加计算负担
  5. 资源占用:虽然轻量,但在资源受限设备上仍需优化

八、替代方案推荐

如果 Snowboy 无法满足需求,可以考虑:

  1. Porcupine(Picovoice):商业级,支持自定义唤醒词
  2. Mycroft Precise:完全开源,可本地训练
  3. TensorFlow Lite:使用 TensorFlow 模型
  4. Vosk:离线语音识别,支持唤醒词

总结

Snowboy 是一个优秀的离线语音唤醒工具,虽然官方支持有所减少,但在许多场景下仍然可用。通过合理的配置和集成,可以构建出功能完善的语音交互系统。对于新项目,建议同时评估其他替代方案,选择最适合的技术栈。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐