16. 使用 Vosk(离线)的语音控制小车
Vosk 是一个轻量级的语音转文字(STT)引擎,支持多种语言,并且可以在树莓派上完全 离线 运行。 你只需联网一次下载语言模型,之后就可以在没有网络连接的情况下正常使用。
在本课程中,我们将:
检查树莓派上的麦克风。
安装并测试 Vosk 的语言模型。
构建一台 语音控制的 PiCar-X,通过唤醒词启动,并识别诸如 forward、backward、left 和 right 等语音指令。
开始之前
确保你已经准备好以下内容:
安装所有模块(重要) — 安装
robot-hat、vilib、picar-x模块,然后运行脚本i2samp.sh。
1. 检查麦克风
在使用语音识别前,先确保你的 USB 麦克风工作正常。
列出可用的录音设备:
arecord -l找到类似
card 1: ... device 0的行。录制一个 3 秒的测试音频(将
1,0替换为上面找到的数字):arecord -D plughw:1,0 -f S16_LE -r 16000 -d 3 test.wav
示例:如果你的设备是
card 2, device 0,使用:
arecord -D plughw:2,0 -f S16_LE -r 16000 -d 3 test.wav
回放录制的音频,确认录音是否成功:
aplay test.wav如果录音声音太小,可以调整麦克风音量:
alsamixer
按 F6 选择你的 USB 麦克风。
找到 Mic 或 Capture 通道。
确保麦克风未静音([MM] 表示静音,按
M解除静音 → 应显示 [OO])。使用 ↑ / ↓ 方向键调整音量。
2. 测试 Vosk
步骤如下:
创建一个新文件:
cd ~/picar-x/example sudo nano test_stt_vosk.py
将以下示例代码复制进去,然后按
Ctrl+X,再按Y和Enter保存退出。from picarx.stt import Vosk vosk = Vosk(language="en-us") print(vosk.available_languages) while True: print("Say something") result = vosk.listen(stream=False) print(result)
运行程序:
sudo python3 test_stt_vosk.py
第一次使用新语言运行时,Vosk 会**自动下载语言模型** (默认下载 small 版本)。 同时会打印支持的语言列表,然后你会看到:
vosk-model-small-en-us-0.15.zip: 100%|███████████████████| 39.3M/39.3M [00:05<00:00, 7.85MB/s] ['ar', 'ar-tn', 'ca', 'cn', 'cs', 'de', 'en-gb', 'en-in', 'en-us', 'eo', 'es', 'fa', 'fr', 'gu', 'hi', 'it', 'ja', 'ko', 'kz', 'nl', 'pl', 'pt', 'ru', 'sv', 'te', 'tg', 'tr', 'ua', 'uz', 'vn'] Say something
这意味着:
模型文件(
vosk-model-small-en-us-0.15)已成功下载。已打印支持的语言列表。
系统正在监听麦克风输入 —— 对 PiCar-X 说话,识别出的文本会实时显示在终端中。
提示:
保持麦克风距离 15–30 厘米。
选择与你的语言和口音匹配的模型。
流式模式(可选)
你也可以使用流式识别模式,在说话时实时查看部分识别结果。
from picarx.stt import Vosk
vosk = Vosk(language="en-us")
while True:
print("Say something")
for result in vosk.listen(stream=True):
if result["done"]:
print(f"final: {result['final']}")
else:
print(f"partial: {result['partial']}", end="\r", flush=True)
3. 语音控制小车
现在,让我们把语音识别和 PiCar-X 连接起来!
我们将使用一个 唤醒词 (”hey robot”),只有当小车被激活后才会监听指令。 这不仅节省 CPU,还可以避免误触发。
运行代码
cd ~/picar-x/example
sudo python3 16.voice_controlled_car.py
在这个程序中,小车将会:
等待唤醒词 “hey robot”。
之后你就可以自然地说话了 —— 只要你的句子中包含以下任一关键词(forward、backward、left、right),小车就会做出对应动作。
例如:
“Can you move forward a little?” → 小车前进。
“Please turn left now.” → 小车左转。
当你说 “sleep” 时,小车会停止控制循环,重新进入等待模式。
代码
from picarx import Picarx
from picarx.stt import Vosk
import time
px = Picarx()
stt = Vosk(language="en-us")
WAKE_WORDS = ["hey robot"]
print('Say "hey robot" to wake me up! Then say: forward / backward / left / right. Say "sleep" to stop listening.')
try:
while True:
# --- wait for wake word once ---
stt.wait_until_heard(WAKE_WORDS)
print("Wake word detected. Listening for commands... (say 'sleep' to pause)")
# --- command loop: multiple commands after one wake ---
while True:
res = stt.listen(stream=False)
text = res.get("text", "") if isinstance(res, dict) else str(res)
text = text.lower().strip()
if not text:
continue
print("Heard:", text)
if "sleep" in text:
# pause command mode; go back to wait for wake word
px.stop(); px.set_dir_servo_angle(0)
print("Sleeping. Say 'hey robot' to wake me again.")
break
elif "forward" in text:
px.set_dir_servo_angle(0)
px.forward(30); time.sleep(1); px.stop()
elif "backward" in text:
px.set_dir_servo_angle(0)
px.backward(30); time.sleep(1); px.stop()
elif "left" in text:
px.set_dir_servo_angle(-25)
px.forward(30); time.sleep(1)
px.stop(); px.set_dir_servo_angle(0)
elif "right" in text:
px.set_dir_servo_angle(25)
px.forward(30); time.sleep(1)
px.stop(); px.set_dir_servo_angle(0)
# (ignore other words)
except KeyboardInterrupt:
pass
finally:
px.stop(); px.set_dir_servo_angle(0)
print("Stopped and centered. Bye.")
故障排查
No such file or directory(运行 `arecord` 时出现)
你可能使用了错误的声卡 / 设备编号。 运行:
arecord -l然后用 USB 麦克风对应的编号替换
1,0。录音文件没有声音
打开混音器检查麦克风音量:
alsamixer
按 F6 选择你的 USB 麦克风。
确保 Mic/Capture 没有被静音(应显示 [OO] 而不是 [MM])。
使用 ↑ 键提高音量。
Vosk 无法识别语音
确保 语言代码 与模型匹配(例如英语为
en-us,中文为zh-cn)。保持麦克风距离 15–30 厘米,并避免背景噪音。
清晰、适中速度地说话。
唤醒词(“hey robot”)无法触发
语气自然,不要太快。
检查程序是否有识别输出,如果没有,说明麦克风可能未正常工作。
识别延迟高 / 速度慢
默认下载的是 small 模型 (速度较快但准确率较低)。
如果仍然较慢,可关闭其他程序释放 CPU。