这套配置的边界很清楚:8GB 内存的 Raspberry Pi 5、Ubuntu 24.04、主动散热,测试记录中的环境温度为 45℃。ASR 使用 Whisper-Tiny.en,回复模型是 4-bit 量化的 phi-3-mini。
项目把 500ms 设为首段语音响应的延迟预算。测试表中的四项耗时分别为 50ms、160ms、220ms 和 60ms,相加得到 490ms。数字看起来已经达标,但计时口径需要先说清楚。
490ms 先别急着下结论
silero-vad 设置了 300ms 的静音判定窗口。用户停下后,系统要等静音持续超过这个阈值,才会把音频切片送入 ASR 队列。
测试表中的 50ms 指 VAD 本地检测和触发耗时,没有包含这段 300ms 的等待。因此,490ms 更适合看作各处理环节的延迟预算,不能直接等同于用户停嘴到听见回复的完整时间。如果标题要强调低于 500ms,正文应明确注明计时起点,以及是否包含静音判定窗口。
还有一个细节:既然系统使用异步队列,最终延迟最好由统一时间戳记录。直接把各环节的局部耗时相加,可以帮助定位瓶颈,但不能代替完整链路的计时。
小模型是这台机器的现实选择
ASR 选用 Whisper-Tiny.en。博客园文章《39M参数撬动百亿市场:Whisper-Tiny.en引领嵌入式语音交互革命》给出的数据是 39M 参数、8.43% 词错误率。词错误率与测试集、口音和噪声条件有关,这个数字不宜直接套到树莓派的实际使用场景。
M5Stack 的 Whisper-tiny 文档提到,Whisper 基于 680,000 小时标注数据训练。它说明了模型的训练背景,但不代表端侧设备上的推理速度。
在当前配置中,faster-whisper 通过 CTranslate2 运行,3—5 秒音频的转录记录约为 150—160ms。量化后的 base 模型延迟接近翻倍,不过这组对比没有给出更多编译和运行参数,只适用于当前测试条件。
这台 8GB 树莓派没有选择 large-v3 或 turbo。AWS 的低延迟实时语音识别部署文章展示的是 GPU 实例和 SageMaker AI 路线,硬件目标与单板计算机不同。对这里的配置来说,Tiny.en 更容易控制内存和响应时间。
回复模型采用 3.8B 参数的 phi-3-mini,通过 llama.cpp 转为 GGUF,并使用 Q4_K_M 量化。4-bit 的直接作用是降低模型占用,减少 8GB 内存设备上的 Swap 压力。当前记录中的首 Token 延迟为 200—300ms,汇总表采用 220ms。
队列能防阻塞,关键路径仍有先后顺序
处理链路可以简化为:
Audio In → silero-vad → Queue_ASR → faster-whisper → Queue_LLM → phi-3-mini → TTS
Python 侧使用 asyncio 组织三个工作单元:
- Audio Worker:持续采集音频并运行 VAD,切片完成后写入
Queue_ASR。 - ASR Worker:调用
faster-whisper,把转录文本写入Queue_LLM。 - LLM Worker:调用
phi-3-mini,生成的 Token 持续写入 TTS 缓冲区。
这里的流式主要发生在 LLM 到 TTS 这一段。Whisper 仍然要等 VAD 完成切片,再处理整段音频,并没有按音频帧持续输出文字。
异步队列可以避免录音、识别和生成互相阻塞,也方便连续处理多轮输入。但对单轮对话来说,ASR 完成后 LLM 才能启动,首 Token 出现后 TTS 才能准备播放,这条关键路径仍有明确的依赖关系。
所谓首字抢跑,是从第一个 Token 到达时就开始填充 TTS 缓冲,而不是等 LLM 生成完整回答。实际播放仍要满足 TTS 引擎可合成的最小文本片段,不能简单把单个 Token 等同于可直接播出的语音。
490ms 由哪些环节组成
| 环节 | 处理内容 | 延迟 | 当前配置 |
|---|---|---|---|
| VAD 检测与触发 | 语音活动检测、推送切片 | 50ms | Silero-VAD 本地运行 |
| ASR 转录 | Whisper-Tiny.en,3—5 秒音频 | 160ms | CTranslate2 / FP16 |
| LLM 首 Token | phi-3-mini TTFT | 220ms | llama.cpp / Q4_K_M |
| TTS 缓冲 | 首个 Token 到语音输出 | 60ms | 预加载语音库、流式播放 |
| 合计 | 四段处理耗时 | 490ms | 不含 300ms 静音判定窗口 |
这张表适合用来找瓶颈:ASR 已经压到 160ms,LLM 的 220ms 是最大单项,TTS 缓冲还有 60ms。若目标是缩短用户停嘴后的完整等待,VAD 的 300ms 端点判定同样需要纳入优化。
几个会直接吃掉延迟的细节
音频从采集端就设为 16kHz。 Whisper 使用 16kHz 输入。当前测试中,如果先以 44.1kHz 采集,再交给 Python 重采样,会增加约 30ms 的 CPU 开销。直接在硬件驱动层设置为 16000Hz,可以省掉这一步。
把 CPU 调度策略固定下来。 默认 ondemand 模式对短时负载的响应会慢一些。测试中使用以下命令切换到高性能模式:
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
当前记录显示,切换后 TTFT 降低约 40ms。这个结果与系统负载、散热和编译参数有关,不应当作所有树莓派都能复现的固定收益。持续使用高性能模式时,主动散热也要保留。
给模型进程留下稳定的内存空间。 phi-3-mini 长时间运行时,内存碎片和 Swap 都可能带来 OOM 或明显卡顿。当前配置关闭桌面环境后释放了约 800MB,并为 llama.cpp 预留固定的内存预算。对 8GB 设备来说,这比多开几个后台服务更实际。
这组数据能说明什么
在给定硬件、系统和散热条件下,Whisper-Tiny.en、Q4_K_M 量化的 phi-3-mini、异步队列与流式 TTS,确实把四段处理预算压到了 490ms。完整的停嘴到出声延迟还要计算 300ms 静音窗口,二者需要分开表述。
这条路线仍有复现价值:ASR 选小模型,LLM 控制在 4-bit,音频直接采集为 16kHz,再让录音、识别和生成通过队列解耦。公开测试结果时,还应同时写明提示词长度、音频片段、CTranslate2 运行参数、llama.cpp 构建方式、TTS 引擎和计时边界。条件写全,490ms 才是一组能被验证的工程数据。