返回

唤醒词检测替代方案:Kaldi, DeepSpeech与阈值方案对比

IOS

唤醒词检测替代方案探讨

基于唤醒词的功能在许多应用中变得常见。尽管Porcupine是性能优异的选择,但其成本可能成为某些项目的障碍。寻找更经济或免费且依然保持较高精度的方案就成为许多开发者的迫切需求。本篇文章旨在探讨一些替代方案,着重解决资源占用和设置复杂性问题。

基于Kaldi的唤醒词检测

Kaldi是一个强大的语音识别工具包,可以用来构建定制的唤醒词检测系统。 相较于预训练的模型,Kaldi允许开发者根据具体需求调整和训练,从而可能达到更高的精度,尤其是针对特定语音环境或特定说话人。

方案原理

使用Kaldi的关键在于利用其模型训练能力,这包括收集足够多的目标唤醒词的音频样本以及非唤醒词的音频数据,训练声学模型和语言模型。 在部署阶段,Kaldi通过计算实时输入的语音片段与训练模型的匹配程度,以此判断是否触发唤醒词。

操作步骤

  1. 环境准备: 安装Kaldi和必要的依赖。不同的操作系统安装步骤会有差异, 需参照Kaldi官方文档进行配置。
# 例如,在Ubuntu上的安装方式
sudo apt-get install wget git subversion
git clone https://github.com/kaldi-asr/kaldi.git kaldi --recursive
cd kaldi/tools
make -j $(nproc)
cd ../src
./configure --shared
make depend -j $(nproc)
make -j $(nproc)
  1. 数据准备: 收集唤醒词音频和非唤醒词音频,并将它们进行分类和标记。 数据量决定模型的性能。通常越多越好。

  2. 模型训练: 使用Kaldi脚本根据准备好的数据训练声学模型和语言模型, 根据实际情况选择不同的训练配方。

# 示例: 在 `egs/librispeech/s5` 目录下
cd egs/librispeech/s5
./run.sh # 或者定制自己的训练脚本
  1. 部署和测试: 将训练好的模型部署到目标应用中,实时进行唤醒词检测。 此处需要根据具体情况进行代码集成。

安全建议

由于Kaldi涉及到音频处理, 需要注意保护用户隐私,不要上传或存储未经过加密的用户语音数据, 并在本地处理数据以保证安全。

使用开源模型: DeepSpeech

DeepSpeech 是 Mozilla 开源的语音识别引擎,虽然主要设计用于语音转文本,也可以通过微调用于唤醒词检测。 该方案优点在于, 有较多的社区支持, 并且容易使用,提供了丰富的预训练模型和API。

方案原理

使用DeepSpeech预训练模型后, 再添加少量目标唤醒词的数据微调模型, 可以将模型的注意力集中在目标唤醒词上。通过分析实时输入的音频,对比是否符合训练时的唤醒词,从而判断是否激活。

操作步骤

  1. 环境准备: 安装DeepSpeech客户端和服务端API.

    # pip 安装
    pip install deepspeech
    
  2. 模型获取: 下载DeepSpeech预训练模型文件和字母模型。

  3. 微调模型: 收集唤醒词音频,然后使用DeepSpeech工具进行微调。 该过程可能需要具备一定的机器学习知识, 需要细致调整参数,以保证模型性能。

  4. 部署和测试: 通过API或客户端将模型集成到应用中。

代码示例(Python)

import deepspeech
import wave

# 创建模型对象,初始化模型文件路径和字母表
model_path = "path/to/your/model.pbmm" # 微调后模型文件
alphabet_path = "path/to/your/alphabet.txt" # 字母模型文件
beam_width = 1024

model = deepspeech.Model(model_path, beam_width)
model.enableExternalScorer("path/to/scorer.scorer")

#  录音或者获取音频流
def process_audio(audio_file):
    w = wave.open(audio_file, 'rb')
    rate = w.getframerate()
    frames = w.getnframes()
    buffer = w.readframes(frames)

    data16 =  np.frombuffer(buffer, dtype=np.int16)  # Convert to a short array

    audio_length = frames / rate

    detected_text = model.stt(data16,rate) #  转换到文本 识别是否有目标词语

    # 返回是否检测到
    return target_wake_word in detected_text.lower()

# 测试,音频文件名为 audio.wav
if process_audio('audio.wav') :
    print("Wake word detected.")
else:
    print("Not detected.")

安全建议

DeepSpeech模型训练和部署需要一定的计算资源, 需要在选择云服务器或本地设备时考虑成本和性能之间的平衡,尤其在涉及到模型微调时, 尽可能保证训练和使用环境的隔离,避免模型文件被恶意利用。

简单阈值方案:VAD和短时能量

一种较为轻量且易于实现的方案是基于VAD(语音活动检测)和短时能量的简单阈值方案。 虽然在噪声环境和复杂语音场景下可能不如上述方案准确,但在资源受限的情况下不失为一种可行的备选方案。

方案原理

VAD用于检测是否存在语音信号。 当检测到语音信号后,分析短时能量,计算当前音频帧的能量大小。 如果连续几帧的能量高于预设阈值, 则可以认为激活唤醒词。

操作步骤

  1. VAD实现: 可以使用WebRTC VAD模块或其它库。

  2. 能量计算: 采用音频帧的均方根作为短时能量的近似值。

  3. 阈值设置: 基于实际场景的音频测试,确定合理的阈值范围。 可以基于测试数据不断调整。

  4. 程序部署: 将上述步骤的代码封装进应用中, 进行实时检测。

代码示例(Python)

import webrtc_vad
import numpy as np
import sounddevice as sd


sample_rate=16000
frame_duration = 20 # in ms
frame_size=int(sample_rate * frame_duration /1000)
vad = webrtc_vad.Vad()
threshold = 0.2

def process_frame(frame):
    frame = np.frombuffer(frame,dtype=np.int16)

    is_speech = vad.is_speech(frame, sample_rate)

    energy= np.sqrt(np.mean(frame**2)) / (2** 15) # Calculate RMS
    return  is_speech and  energy > threshold
   
    
# 音频输入(如麦克风输入),检测唤醒词
try:
    while True:
        data, overflowed = sd.rec(frame_size,sample_rate,channels=1,dtype='int16',blocking=True)

        is_triggered= process_frame(data)

        if  is_triggered:
            print('Wake word activated!')
        
except sd.PortAudioError as e:
    print('ERROR:', str(e))    

安全建议

该方案安全性较低, 因为不依赖特定的唤醒词模型, 因此,不适用于安全性要求高的场景,且容易被噪声激活,应合理部署。

总结

为满足各种应用的需求, 开发者可选择多种唤醒词检测的替代方案。 基于Kaldi方案可进行精细调整, 精度高但设置较为复杂; DeepSpeech拥有易用的接口和社区支持; 阈值方案简单轻量,资源消耗小但鲁棒性不高。 各方案适用不同的场景和资源限制。 在选择方案时应考虑应用的精度要求,计算资源, 以及开发周期和技术难度, 才能最终选择合适的方案,提升整体效率。