news 2026/4/16 14:10:36

【学习心得】基于VOSK的唤醒词检测

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【学习心得】基于VOSK的唤醒词检测

VOSK 是一个开源的语音识别(ASR,Automatic Speech Recognition)工具包,主要用于将语音转换成文本。它支持多种语言,可以在离线环境下运行,适合嵌入式设备、移动端应用,或者需要低延迟、高隐私的场景。VOSK 的核心优势包括轻量级、跨平台(支持 Windows、Linux、Android、iOS 等),以及提供预训练模型,方便快速集成。它基于 Kaldi 语音识别工具链,但使用起来更加简洁,适合开发者快速搭建 ASR 系统。

VOSK 主要特点如下表:

特性说明
离线运行无需联网,所有模型本地运行,保障用户隐私。
多语言支持支持中文(普通话)、英语、俄语、法语、德语、西班牙语等数十种语言。
轻量高效模型体积小(如中文模型约50MB),内存占用低,适用于树莓派、手机等资源受限设备。
实时流式识别支持连续语音输入,可逐字返回部分识别结果(partial results),适合实时转录或语音助手。
跨平台提供 Python、Java、C#、Node.js、Go、Rust 等语言绑定,兼容 Linux、Windows、macOS、Android 和 iOS。
开源免费采用 Apache 2.0 许可证,可自由用于商业项目。

VOSK的官方模型下载页:vosk models

一、安装环境

vosk 和 sounddevice 是两个常用于语音识别(ASR)和音频处理的 Python 库。vosk 是 VOSK 语音识别工具包的 Python 接口,用于实现离线语音识别(ASR)。适用场景:本地语音转文字、实时语音助手、语音命令控制等。
sounddevice 是一个用于实时音频录制和播放的 Python 库,可以方便地获取麦克风输入或输出音频。提供类似 NumPy 的接口,便于处理音频数据。支持低延迟实时音频流。适合与 vosk 配合使用,将麦克风采集的音频流送入语音识别模型。适用场景:实时语音采集、音频流处理、语音识别的音频输入端。

# 安装 Python 依赖: vosk 、 sounddevice pip install vosk sounddevice

【注】在基于 Debian 或 Ubuntu 的 Linux 系统上,安装sounddevice这个 Python 库所依赖的一个底层系统库:libportaudio2sounddevice库准备好它所依赖的底层音频驱动环境

# 安装系统库: libportaudio2 (用于 sounddevice ) apt-get update && apt-get install -y libportaudio2

二、使用教程

# 导入队列库,用于线程安全地传递音频数据 import queue import json # 导入 sounddevice 库,用于从麦克风实时采集音频流,并简称为 sd import sounddevice as sd # 从 vosk 库中导入 Model(加载语音识别模型)和 KaldiRecognizer(识别器核心) from vosk import Model, KaldiRecognizer # --- 1. 全局参数设置 --- # 设置 VOSK 模型的文件夹路径。你需要下载一个模型并解压到此路径。 # 例如:'vosk-model-small-zh-cn-0.22' model_path = "vosk-model-small-cn-0.22" # 替换为你的vosk模型路径 # 设置音频采样率。VOSK 模型通常在 16000 Hz 下训练,所以这里也用这个值。 samplerate = 16000 # 确保此采样率与您的麦克风设置匹配 # 定义一个唤醒词。当识别到这个词时,程序会做出反应。 wake_word = "船长" # 定义唤醒词 # 创建一个队列对象。回调函数会把音频数据放进这个队列,主线程再从中取出。 # 这是处理流式数据时避免阻塞的常用方法。 q = queue.Queue() # --- 2. 音频数据回调函数 --- def callback(indata, frames, time, status): """ 这是 sounddevice 库的回调函数。 它会在一个独立的线程中被反复调用,每次处理一小块音频数据。 """ # 如果 status 不为空,说明音频流出现了问题(如缓冲区溢出),打印错误信息。 if status: print(status, flush=True) # 将从麦克风采集到的音频数据(indata)转换成字节流,然后放入队列 q 中。 # indata 是一个 NumPy 数组,需要转换成 VOSK 识别器能处理的 bytes 格式。 q.put(bytes(indata)) # print(f"Received {len(indata)} bytes") # 音频流是否正常 # --- 3. 主程序逻辑 --- try: # --- 3.1 初始化模型和识别器 --- # 加载指定路径的 VOSK 模型。这是一个耗时操作,通常只做一次。 model = Model(model_path) # --- 3.2 启动音频流 --- # 使用 sd.RawInputStream 创建一个原始音频输入流。 # 这会持续在后台采集麦克风数据,并通过 callback 函数处理。 with sd.RawInputStream(samplerate=samplerate, blocksize=8000, dtype='int16', channels=1, callback=callback): # 打印提示信息,告诉用户程序已经开始监听。 print("开始监听唤醒词...") # 创建一个 KaldiRecognizer 识别器实例,并将加载好的模型和采样率传给它。 rec = KaldiRecognizer(model, samplerate) # --- 3.3 持续监听和识别循环 --- # 进入一个无限循环,持续处理音频数据,直到检测到唤醒词或程序被中断。 while True: # 从队列中获取一小块音频数据。如果队列为空,q.get() 会阻塞,直到有数据可用。 data = q.get() # 将获取到的音频数据喂给识别器。 # AcceptWaveform 方法会处理这份数据,并返回一个布尔值: # 如果返回 True,表示 VOSK 认为已经说完了完整的一句话(有静音停顿)。 if rec.AcceptWaveform(data): # 获取当前这句完整话的识别结果(JSON 格式的字符串)。 result = rec.Result() # 使用 eval() 将 JSON 字符串解析成 Python 字典。 result_dict = json.loads(result) recognized_text = result_dict.get("text", "").replace(" ", "") # 去除识别结果中的所有空格再匹配 print("VOSK Result:", recognized_text) # 确认 VOSK 是否识别出了内容 # 检查字典中是否存在 'text' 键,并且唤醒词是否在识别出的文本中。 # .lower() 是为了进行大小写不敏感的匹配。 if wake_word in recognized_text: # 如果检测到唤醒词,打印提示信息。 print(f"唤醒词 '{wake_word}' 被检测到!") # 在这里执行唤醒后的操作,例如:开始录音、播放回应、启动某个功能等。 # 示例中我们直接 break 退出循环。 break # --- 4. 异常处理 --- except KeyboardInterrupt: # 如果用户按下 Ctrl+C,会触发 KeyboardInterrupt 异常。 # 捕获它并打印一个友好的停止信息。 print("\n停止监听") except Exception as e: # 捕获其他所有可能的异常(如模型路径错误、麦克风权限问题等)。 # 打印出具体的错误信息,方便调试。 print(str(e))

三、核心方法介绍

(1)vosk库核心方法/对象

方法 / 对象用途说明关键细节
Model(model_path)加载本地语音识别模型必须传入解压后的模型文件夹路径(不是.zip文件),模型语言需与唤醒词一致(如中文用zh-cn模型)。只需初始化一次,耗时但可复用。
KaldiRecognizer(model, samplerate)创建语音识别器实例samplerate必须与音频输入采样率一致(通常为 16000)。支持流式识别,内部维护状态。
rec.AcceptWaveform(data)向识别器喂入一段音频数据(bytes)data必须是int16格式的原始 PCM 字节流,返回True表示识别出一个完整语句(有静音边界)。即使返回False,也可能有部分结果(可用rec.PartialResult()获取)。
rec.Result()获取上一句完整语音的识别结果返回 JSON 字符串,如'{"text": "你好 小助手"}'。仅在AcceptWaveform返回True后调用才有意义。
rec.PartialResult()(可选)获取当前正在说的不完整文本用于实时显示“正在听你说...”效果。在唤醒词检测中一般不需要。

(2)sounddevice库核心方法/对象

方法 / 对象用途说明关键细节
sd.RawInputStream(...)创建原始音频输入流(从麦克风实时采集)samplerate=16000:必须与 VOSK 模型训练采样率一致
channels=1:单声道(VOSK 不支持立体声)
dtype='int16':16位有符号整数(PCM 标准格式)
callback:每次采集到一块音频就自动调用该函数(在后台线程运行)
callback(indata, frames, time, status)音频回调函数indata是 NumPy 数组,需转为bytes才能被 VOSK 使用
此函数不能做耗时操作(会阻塞音频流)
通常只做“把数据放进队列”这种轻量操作
sd.query_devices()(调试用)列出系统所有音频设备用于查找麦克风的device index。如果默认设备不对,可在RawInputStream中指定device=2
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 10:42:34

Delphi凭什么挑战Excel VBA?背后深意很多人没看懂

说 Delphi 死了的人,大多没真正用过它。而说 Excel VBA 万能的人,基本都还没被业务折磨够。就在我上一篇写 Python 和 VBA 的文章下面,有读者突然冒出一句话:delphi7 才是Excel编程神器。相信这句话戳中了不少老程序员用过delphi的…

作者头像 李华
网站建设 2026/4/10 6:18:06

SimulCrypt 与 BISS:线性电视中的内容保护机制

在线性广播中,内容保护是任何 DVB 或 IPTV 网络的基础组成部分。广播商——包括卫星、有线和 IPTV 运营商——在内容制作和采购上投入巨大。借助加密技术,他们能够通过销售订阅服务、控制访问权限来实现内容变现,并防止未经授权的复制或再分发…

作者头像 李华
网站建设 2026/4/16 12:22:18

化妆品“拼团全返”模式深度解析:23天1400万背后的商业逻辑

去年7月,某化妆品企业在23天的短期活动中,实现销售额约1400万元,积累参与用户50万名。活动以一款标价87元的口红为核心产品,通过“拼团返积分”机制促进用户参与。该机制的实施可分为以下步骤:一、搭建线上销售平台企业…

作者头像 李华
网站建设 2026/4/16 11:05:25

将组建一支“多国部队”支持乌克兰,德国、法国、英国、意大利、波兰、芬兰、挪威、瑞典、荷兰等发表联合声明!

据央视消息,当地时间15日晚间,德国、法国、英国、意大利、波兰、芬兰、挪威、瑞典、荷兰及欧盟机构领导人发表联合声明称,将组建一支“多国部队”支持乌克兰。 声明称“该部队将协助乌克兰重建武装力量、保障乌克兰领空安全,并提…

作者头像 李华
网站建设 2026/4/16 10:43:23

科研绘图中的色卡选择与高级 Colorbar 设计

Matplotlib 进阶:做一个“两头尖尖”的竖直色条,并自动命名保存 在做论文图/报告图时,常规的矩形 colorbar 有时不够“视觉友好”。比如我最近需要一个竖直、窄而高、上下两端尖尖的色条(类似箭头端帽),同…

作者头像 李华
网站建设 2026/4/16 10:59:10

Leetcode刷题日记17(161-170)

目录问题1:问题链接:问题描述:实例:代码:问题2:问题链接:问题描述:实例:代码:问题3:问题链接:问题描述:实例:代…

作者头像 李华