树莓派4B离线语音助手搭建:基于sherpa-onnx的本地语音识别与合成实战
前阵子收拾仓库翻出一块吃灰两年的树莓派4B插上电发现系统还是2020年烧录的旧版本本来想装个语音助手玩智能家居结果看一眼主流方案要么依赖云端API要么需要长期挂着网络断网就成哑巴。后来我换了思路直接用sherpa-onnx在本地做语音识别和语音合成把整个语音助手完全跑在树莓派上不联网、不注册账号、不传音频出去实测从烧录系统到语音对话跑通大概一刻钟左右就能搞定。这篇内容就把完整流程拆开来讲包括sherpa-onnx的核心原理、树莓派上的环境准备、模型选择和麦克风音频采集还有我踩过的坑和最终的成品代码。适合手里有树莓派、想做一个完全本地化语音助手的朋友哪怕之前没碰过音频处理和语音识别按步骤走也能跑起来。1. 核心思路拆解为什么选sherpa-onnx做离线语音助手1.1 离线方案对比为什么放弃云端API做语音助手市面上常见的几条路我基本都试过。最早用的是某度语音API识别效果确实不错但有个绕不开的问题音频要上传到服务器识别结果再返回一来一回延迟不说隐私上也有顾虑。后来试过在树莓派上跑home-assistant加云端组件效果还行但每次断网整个语音控制就瘫痪体验非常割裂。真正让我决定走全离线路线的是一次弱网环境下测试智能家居控制喊了三遍“打开客厅灯”语音助手一点反应没有那一刻我意识到依赖网络的服务永远受制于网络质量。离线语音助手的核心价值就在这里所有音频数据在本地处理识别和合成都不需要外部网络响应速度更快隐私完全可控断网不断用。1.2 sherpa-onnx是什么为什么适合树莓派sherpa-onnx是一个基于ONNX Runtime的离线语音处理工具集由k2-fsa社区维护。它把语音识别、语音合成、说话人识别、语音活动检测等功能全部封装成跨平台的推理接口模型经过ONNX格式转换后可以在CPU上高效运行不需要GPU加速。我选它的主要原因有三个。第一模型全离线支持中文识别和中文语音合成不需要额外搭建服务端。第二推理框架足够轻量树莓派4B这种ARM平台设备完全跑得动CPU占用和内存开销都在可接受范围。第三支持Python和C两种API接入方式灵活还能自定义唤醒词。拿树莓派4B来说4GB版本跑sherpa-onnx的流式识别模型CPU占用大概在30%到50%之间识别延迟在几百毫秒到一秒左右对于本地语音助手来说这个性能完全够用。如果是树莓派5性能会更好模型推理速度能快不少。1.3 语音助手的整体架构一个完整的离线语音助手逻辑上可以拆成四个部分音频采集通过USB麦克风或3.5mm接口麦克风采集用户语音需要处理ALSA设备选择和采样率配置。语音识别将音频流送入sherpa-onnx的识别模型转成文本。意图理解与执行识别出的文本做简单的关键词匹配映射到对应操作比如开灯、关灯、查天气本地数据。语音合成把反馈文本通过sherpa-onnx的TTS模型转成音频播放出来。这四个部分在树莓派上串起来就是一个完整的语音对话闭环。sherpa-onnx承担识别和合成这两个最核心的模块我只需要在Python层面处理音频流和业务逻辑整体开发成本不高。2. 树莓派4B系统准备与环境依赖2.1 系统选择与烧录树莓派4B可以跑官方Raspberry Pi OS也可以跑Ubuntu Server。考虑到sherpa-onnx的预编译包对各种Linux发行版的兼容情况我建议直接用Raspberry Pi OS64位版本原因有几个官方系统对树莓派的硬件支持最完善ALSA音频驱动、I2C、GPIO等开箱即用。sherpa-onnx提供armv7l和aarch64两种架构的预编译包都优先针对Debian系测试过依赖问题最少。社区资料最多遇到问题更容易搜到解决方案。烧录方式很简单用Raspberry Pi Imager工具选择系统镜像后直接写入SD卡。注意树莓派4B一定要选64位系统32位系统上sherpa-onnx的部分模型推理速度会明显偏慢。提示写系统前先准备好一张至少32GB的TF卡Class 10或以上等级写入速度和稳定性都会更好。如果手头有多张卡尽量选A2规格的随机读写性能更好树莓派启动和模型加载会更顺畅。2.2 系统初始化与换源烧录完成后开机进入系统先执行系统更新sudo apt update sudo apt upgrade -y这里有个实际操作细节树莓派官方的软件源服务器在国外如果网络条件不太理想更新速度会很慢建议先换国内镜像源。编辑/etc/apt/sources.list和/etc/apt/sources.list.d/raspi.list把默认的archive.raspberrypi.org和deb.debian.org替换成国内镜像地址比如清华、阿里云的源。换源之后重新执行sudo apt update sudo apt upgrade -y实测换源后更新速度能提升好几倍依赖安装的体感顺畅很多。注意别忘了检查时区。如果树莓派的时间不准音频时间戳和日志记录都会有问题。执行sudo raspi-config在Localisation Options里设置时区为Asia/Shanghai并开启NTP同步。2.3 安装Python环境和基础依赖sherpa-onnx的Python包支持Python 3.7到3.12树莓派系统自带的Python版本通常够用。建议用venv创建独立环境避免干扰系统级包。sudo apt install -y python3-venv python3-pip mkdir -p ~/voice-assistant cd ~/voice-assistant python3 -m venv venv source venv/bin/activate重点来了先升级pip再装依赖否则安装sherpa-onnx时可能遇到编译问题。pip install --upgrade pip setuptools wheel然后安装sherpa-onnxpip install sherpa-onnx这个包会自动拉取ONNX Runtime等依赖如果网络正常装起来比较顺利。装完验证一下python -c import sherpa_onnx; print(sherpa_onnx.__version__)能够输出版本号说明安装成功。2.4 音频设备配置与依赖语音助手离不开麦克风音频采集这也是最容易出问题的一环。树莓派板载没有麦克风接口需要外接USB麦克风或者USB声卡加模拟麦克风。插上USB麦克风后先查看系统是否正确识别arecord -l正常情况会输出类似**** List of CAPTURE Hardware Devices **** card 1: Microphone [USB Audio], device 0: USB Audio [USB Audio] Subdevices: 1/1 Subdevice #0: subdevice #0记下这个card编号和device编号后面配置音频参数和代码里要用到。如果arecord -l没有输出任何设备先检查USB接口接触是否良好再试其他USB口部分树莓派电源供电不足会导致USB设备无法被识别。确保有录音设备后安装音频处理相关的系统依赖sudo apt install -y libportaudio2 portaudio19-dev python3-pyaudiosherpa-onnx的Python包本身支持从麦克风直接读取音频但在树莓派上直接调用会有缓冲问题所以我更倾向于用Python的sounddevice库来做音频采集再喂给sherpa-onnx识别这样遇到延迟和缓冲问题时方便调参。pip install sounddevice numpy3. 模型下载与配置选型3.1 模型选择识别模型和TTS模型sherpa-onnx的模型都在GitHub的k2-fsa/sherpa-onnx仓库下面模型文件放在Releases页面也支持直接从Hugging Face下载。官方提供了很多预训练模型涵盖不同语言、不同架构、流式和非流式等。对于树莓派上的中文离线语音助手我的建议是识别模型选 Zipformer 系列的流式模型比如sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20。这个模型支持中文和英文混合识别流式推理延迟低树莓派上跑起来很稳。TTS模型选 VITS 系列的中文模型比如sherpa-onnx-vits-zh-ll。VITS是端到端的语音合成模型直接在ONNX Runtime上推理生成的语音自然度不错树莓派上单次合成也能在几百毫秒到一两秒内完成。提示不要选太大的模型。之前在树莓派上试过一个大参数量的识别模型内存占用直接破2GB4B版本勉强能跑但卡顿严重5版本会好一些。树莓派4B建议选zipformer蒸馏版或者较小参数量的模型性能与准确率平衡最好。3.2 下载模型文件为了方便管理我习惯把模型统一放在项目目录下的models文件夹里。mkdir -p ~/voice-assistant/models cd ~/voice-assistant/models对于中文流式识别模型可以直接从GitHub Releases下载这里以识别模型为例wget https://github.com/k2-fsa/sherpa-onnx/releases/download/asr-models/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2 tar xvf sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20.tar.bz2TTS模型同理wget https://github.com/k2-fsa/sherpa-onnx/releases/download/tts-models/sherpa-onnx-vits-zh-ll.tar.bz2 tar xvf sherpa-onnx-vits-zh-ll.tar.bz2下载完解压后确认目录结构识别模型目录下包含encoder.onnx、decoder.onnx、joiner.onnx三个推理文件以及tokens.txt词表文件TTS模型目录下包含model.onnx、lexicon.txt等文件后续代码中需要用到这些路径。注意模型文件名里的日期后缀例如2023-02-20代表训练数据的截止时间并不代表版本过时。这些模型在离线场景下依然有很好的识别效果不必追求更新日期的模型。3.3 离线模型管理与快速加载验证模型文件下载好后最好先离线把模型加载一遍确认文件完整、推理链路通顺再写完整程序。这一步可以避免后面程序出问题时搞不清是模型问题还是代码问题。写一个简单的模型加载测试脚本import sherpa_onnx import time recognizer sherpa_onnx.OnlineRecognizer.from_transducer( tokensmodels/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/tokens.txt, encodermodels/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/encoder.onnx, decodermodels/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/decoder.onnx, joinermodels/sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/joiner.onnx, num_threads2, sample_rate16000, feature_dim80, enable_endpoint_detectionTrue, rule1_min_trailing_silence2.4, rule2_min_trailing_silence1.2, rule3_min_utterance_length300, ) print(模型加载成功耗时:, time.time() - start_time)这个脚本就是验证ONNX模型能否正常加载、推理引擎能否正常启动。num_threads参数在树莓派上设2到4都可以线程数越多CPU占用越高但推理延迟并不一定线性下降需要实测权衡。4. 实操过程5分钟跑通核心语音流程4.1 麦克风实时音频采集sherpa-onnx的官方Python示例里有用sounddevice做音频采集的例子。核心逻辑是打开音频输入流把采集到的音频数据按块chunk送入识别器的输入缓冲区同时不断从识别器读取识别结果。在树莓派上跑实时音频采集要注意采样率和数据格式。sherpa-onnx的识别模型固定使用16kHz采样率、单声道、16位PCM数据。USB麦克风通常默认是48kHz必须做重采样否则识别效果会变得非常差。我用的采集代码非常简单import sounddevice as sd import numpy as np sample_rate 16000 channels 1 def audio_callback(indata, frames, time_info, status): if status: print(音频状态异常:, status) # indata 是 float32 格式范围-1到1转换为int16 PCM pcm_data (indata[:, 0] * 32767).astype(np.int16) stream_buffer.extend(pcm_data.tobytes()) stream sd.InputStream( sampleratesample_rate, channelschannels, dtypefloat32, blocksize3200, # 每次采集200ms音频3200/160000.2秒 callbackaudio_callback, ) stream.start()这里blocksize3200对应200毫秒的音频帧长度。200毫秒是一个比较合理的值太长会增加延迟感太短会频繁触发回调增加CPU开销。如果是树莓派4B实测200毫秒是一个比较稳的平衡点。4.2 sherpa-onnx流式识别流程流式识别是离线语音助手的核心。它的工作机制是识别器内部维护一个状态每次喂入一部分音频识别器根据历史音频和当前音频更新识别结果返回当前已经识别出的文本。这个过程是增量式的不用等整句话说完才开始识别。官方示例里的流式识别循环结构很清晰stream recognizer.create_stream() while True: # 从麦克风采集200ms audio data if stream_buffer.has_enough_data(): pcm stream_buffer.read(3200) # 3200个采样点 stream.accept_waveform(16000, pcm) while recognizer.is_ready(stream): recognizer.decode_stream(stream) text recognizer.get_result(stream) if text ! : print(识别结果:, text)每次采集到音频后把PCM数据送入accept_waveform然后调用decode_stream让模型解码最后通过get_result拿到当前识别文本。这里有个细节要注意is_ready和decode_stream需要在一个循环里反复调用因为某些模型的解码器需要多轮迭代才能输出稳定的结果。如果只调用一次decode_stream就急着拿结果可能会漏掉部分识别内容。树莓派上跑这个识别循环CPU占用大约30%到50%内存占用根据模型大小不同在300MB到800MB浮动。整体性能是可以接受的识别一句“打开客厅灯”大约需要0.5到1.5秒。4.3 语音合成与播放识别出文本以后按照预设的规则匹配得到回复文本然后交给TTS模型合成语音播放出来。sherpa-onnx的VITS模型合成中文语音流程相对简单import sherpa_onnx import sounddevice as sd import numpy as np tts_config sherpa_onnx.OfflineTtsConfig( modelsherpa_onnx.OfflineTtsModelConfig( vitssherpa_onnx.OfflineTtsVitsModelConfig( modelmodels/sherpa-onnx-vits-zh-ll/model.onnx, lexiconmodels/sherpa-onnx-vits-zh-ll/lexicon.txt, dict_dirmodels/sherpa-onnx-vits-zh-ll/dict, tokensmodels/sherpa-onnx-vits-zh-ll/tokens.txt, ), num_threads2, ), rule_fstsmodels/sherpa-onnx-vits-zh-ll/date.fst,models/sherpa-onnx-vits-zh-ll/phone.fst, ) tts sherpa_onnx.OfflineTts(tts_config) audio tts.generate(好的已为你打开客厅灯, sid10, speed1.0) # audio.samples 是 float32 数组audio.sample_rate 是采样率 sd.play(audio.samples, samplerateaudio.sample_rate) sd.wait()VITS模型生成音频的速度在树莓派4B上大约比实时快1到3倍也就是说生成5秒的语音大概需要2到4秒。音色可以通过sid参数调整不同模型支持不同数量的说话人。这个中文VITS模型自带多个音色可以在官方模型说明里查各sid对应的风格。提示如果播放时有杂音或爆音大概率是音频设备采样率和TTS模型的采样率不匹配。TTS输出的采样率通常是22050或44100而树莓派的USB声卡可能固定在48000需要重采样。最简单的方案是用sd.play的samplerate参数直接指定TTS输出的采样率让sounddevice自行处理重采样实测效果比手动重采样更稳。4.4 意图匹配与执行逻辑语音助手的“智能”部分其实就是一个文本到动作的映射。不需要上大模型针对常见的控制指令做关键词匹配就够用。我写的规则比较简单def match_intent(text): text text.lower() commands [] if 开灯 in text: commands.append(light_on) if 关灯 in text: commands.append(light_off) if 温度 in text or 室温 in text: commands.append(query_temp) if 你是谁 in text: commands.append(who_are_you) return commands匹配到意图后执行对应的动作并生成回复文本。比如“开灯”对应GPIO拉高电平可以用RPi.GPIO库控制继电器import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setup(17, GPIO.OUT) if light_on in commands: GPIO.output(17, GPIO.HIGH) reply 好的已为你打开客厅灯 elif light_off in commands: GPIO.output(17, GPIO.LOW) reply 好的已为你关闭客厅灯如果要接入更多智能家居设备可以在这里调用MQTT、HTTP接口或者Home Assistant的本地API把语音指令变成统一的消息事件。5. 完整项目代码与流程整合5.1 项目文件结构跑通核心环节后我把整个项目整理成一个结构清晰的仓库voice-assistant/ ├── main.py ├── assistant/ │ ├── __init__.py │ ├── audio.py # 音频采集与播放封装 │ ├── asr.py # 语音识别封装 │ ├── tts.py # 语音合成封装 │ ├── intent.py # 意图识别与动作执行 │ └── config.py # 模型路径与参数配置 ├── models/ │ ├── sherpa-onnx-streaming-zipformer-bilingual-zh-en-2023-02-20/ │ └── sherpa-onnx-vits-zh-ll/ └── requirements.txt模块化拆分之后后面想加新功能比如添加唤醒词、增加新设备控制都只需要改动局部模块整体扩展性要好很多。5.2 主程序代码主程序的逻辑是初始化ASR和TTS模块启动音频采集循环识别音频匹配意图执行动作合成回复播放。import threading import queue import numpy as np import sounddevice as sd import sherpa_onnx from assistant.config import ASR_MODEL_DIR, TTS_MODEL_DIR, SAMPLE_RATE, BLOCK_SIZE class VoiceAssistant: def __init__(self): self.audio_queue queue.Queue() self.recognizer self._init_asr() self.tts self._init_tts() self.is_speaking False def _init_asr(self): return sherpa_onnx.OnlineRecognizer.from_transducer( tokensf{ASR_MODEL_DIR}/tokens.txt, encoderf{ASR_MODEL_DIR}/encoder.onnx, decoderf{ASR_MODEL_DIR}/decoder.onnx, joinerf{ASR_MODEL_DIR}/joiner.onnx, num_threads4, sample_rate16000, feature_dim80, enable_endpoint_detectionTrue, ) def _init_tts(self): tts_config sherpa_onnx.OfflineTtsConfig( modelsherpa_onnx.OfflineTtsModelConfig( vitssherpa_onnx.OfflineTtsVitsModelConfig( modelf{TTS_MODEL_DIR}/model.onnx, lexiconf{TTS_MODEL_DIR}/lexicon.txt, dict_dirf{TTS_MODEL_DIR}/dict, tokensf{TTS_MODEL_DIR}/tokens.txt, ), num_threads2, ), rule_fstsf{TTS_MODEL_DIR}/date.fst,{TTS_MODEL_DIR}/phone.fst, ) return sherpa_onnx.OfflineTts(tts_config) def audio_callback(self, indata, frames, time_info, status): if status: return pcm (indata[:, 0] * 32767).astype(np.int16) self.audio_queue.put(pcm.tobytes()) def recognize_loop(self): stream self.recognizer.create_stream() while True: pcm_bytes self.audio_queue.get() samples np.frombuffer(pcm_bytes, dtypenp.int16) stream.accept_waveform(16000, samples.tolist()) while self.recognizer.is_ready(stream): self.recognizer.decode_stream(stream) text self.recognizer.get_result(stream).strip() if text: print([识别], text) self.handle_intent(text) self.recognizer.reset(stream) def handle_intent(self, text): if 开灯 in text: self.speak(好的已为你打开客厅灯) # TODO: GPIO 控制逻辑 elif 关灯 in text: self.speak(好的已为你关闭客厅灯) elif 你是谁 in text: self.speak(我是运行在树莓派上的离线语音助手) else: self.speak(抱歉我没有听懂你的指令) def speak(self, text): self.is_speaking True audio self.tts.generate(text, sid10, speed1.0) sd.play(audio.samples, samplerateaudio.sample_rate) sd.wait() self.is_speaking False def run(self): asr_thread threading.Thread(targetself.recognize_loop, daemonTrue) asr_thread.start() with sd.InputStream( samplerate16000, channels1, dtypefloat32, blocksize3200, callbackself.audio_callback, ): print(离线语音助手已启动等待指令...) while True: pass if __name__ __main__: assistant VoiceAssistant() assistant.run()这段代码就是整个语音助手的骨架。实际运行中可以感受到一个完整的交互闭环对着麦克风说“打开客厅灯”一秒钟左右看到屏幕输出识别结果再过一两秒听到语音回复。整个过程完全离线。5.3 开机自启动配置语音助手放在智能家居环境里不可能每次手动SSH登录启动配置开机自启是必须的。用systemd服务管理最省心。[Unit] DescriptionOffline Voice Assistant Afternetwork.target sound.target [Service] Userpi WorkingDirectory/home/pi/voice-assistant ExecStart/home/pi/voice-assistant/venv/bin/python /home/pi/voice-assistant/main.py Restartalways RestartSec3 [Install] WantedBymulti-user.target把服务文件放到/etc/systemd/system/voice-assistant.service然后执行sudo systemctl daemon-reload sudo systemctl enable voice-assistant sudo systemctl start voice-assistant开机自启配置好之后树莓派上电就能自动进入语音助手工作状态不需要人工干预。6. 常见问题与排查技巧实录6.1 音频设备识别异常问题表现arecord -l没有任何输出或者sounddevice报No audio device found。排查思路先确认USB设备是否被系统识别执行lsusb看有没有USB Audio设备。如果lsusb能看到设备但arecord -l识别不到多半是驱动问题执行sudo apt install alsa-utils重装ALSA工具重启再试。树莓派电源供电不足也会导致USB设备掉线。我之前用5V 2A的手机充电头供电插上USB麦克风后经常随机掉设备换了官方5V 3A电源后问题彻底消失。6.2 识别结果为空或乱码问题表现程序运行正常但识别出来的文本是空字符串或者乱码。排查思路确认采样率是16000Hz。很多USB麦克风默认48kHz如果采集程序没有重采样识别器会收到畸形的音频数据出来的结果自然不对。确认音频通道是单声道。sherpa-onnx的模型只接受单声道PCM直接用双声道数据喂入会出问题。检查麦克风增益。树莓派板载声卡增益普遍偏低输入音量太小识别不出来。可以执行alsamixer找到Mic输入把捕获增益调到合适范围通常60%到80%左右比较合适。alsamixer # F4 切换到捕获设备 # 方向键调整Mic音量 # Esc 保存退出6.3 TTS声音卡顿或断断续续问题表现TTS生成的语音播放时卡顿或者播放到一半停止。排查思路最常见的坑是sd.play和录音线程同时操作声卡导致竞争。我的处理方案是在播放语音前设置is_speaking标志识别循环在播放期间暂停接收新音频避免音频数据竞争。树莓派的音频输出保持在HDMI或3.5mm耳机口。在raspi-config里可以设置默认音频输出如果想强制使用某一路可以在/etc/asound.conf里手动匹配设备。6.4 CPU占用过高导致系统卡顿问题表现语音助手运行后树莓派整体响应变慢甚至SSH操作都卡。排查思路降低num_threads参数。ASR推理线程数从4降到2CPU占用可以明显下降识别延迟略有增加但在可接受范围内。TTS的num_threads同理降为1或2。检查是否有其他常驻进程占用CPU例如rpi-update、索引服务等。执行top或htop排查。提示树莓派4B的散热很重要。跑语音助手连续工作几小时后如果CPU散热片没贴好温度破85度会触发降频整体性能大降。我用的是铝合金被动散热壳实测满载温度稳定在70度左右效果很好。6.5 识别延迟太高问题表现每说完一句话到识别结果出现需要等2秒以上。排查思路确认开启流式识别。非流式模型需要说完一整句才能识别延迟明显更高流式模型在说话过程中就能持续输出结果最终结果几乎在话说完的同时出现。降低音频块大小。原代码里采集块是200ms如果延迟不可接受可以降到100ms即blocksize1600但CPU占用会略微上升。如果条件允许换树莓派5识别速度会有明显提升。6.6 常见问题速查表问题现象大概率原因解决方案没有识别结果采样率不是16000Hz重采样到16k单声道识别结果是乱码输入音频格式错误确认喂入的是PCM int16数据TTS播放卡顿录音线程和播放线程冲突播放时暂停录音或单独用队列串行处理设备偶发掉线电源供电不足换5V 3A高质量电源开机后服务无法启动音频设备未就绪systemd配置里增加Aftersound.target和重启策略7. 效率提升与扩展方向7.1 唤醒词支持当前的实现是持续监听所有环境声音都会被送进识别器这会带来两个问题一是CPU持续占用高二是环境噪音可能导致误识别。更合理的方案是加入唤醒词。sherpa-onnx官方有sherpa-onnx-keyword-spotter工具基于流式模型检测特定唤醒词比如“小树小树”检测到之后才启动真正的语音识别。我自己试过这个方案效果不错。唤醒词检测模型的资源占用极低树莓派上几乎可以7x24小时运行只有当唤醒词出现时才会进入完整识别流程功耗和误识别率都降下来了。代码逻辑相似加载一个keyword spotter模型在音频回调里判断是否命中唤醒词。7.2 接入更多本地服务离线语音助手的扩展方向并不局限在GPIO控制。树莓派上可以跑Home Assistant配合MQTT协议语音助手就变成全屋智能的控制入口。识别出“打开卧室空调”通过MQTT发一条消息相应的设备就会响应。另外本地还可以放一些简单的事实查询比如内置一个天气数据文件识别到“今天温度”就从本地文件读取数据回复不依赖网络。7.3 双麦克风阵列和降噪如果预算充足可以考虑USB双麦克风阵列。sherpa-onnx支持麦克风阵列的音频处理配合降噪算法远场识别的准确率会明显优于单麦克风。不过树莓派4B上跑麦克风阵列的音频处理CPU开销不小需要评估实际需求。我家客厅大概20平单麦克风在3米内的识别准确率还行5米以上就开始明显下降这个距离瓶颈暂时靠语音助手的固定摆放位置缓解。8. 整体感受与最后提示跑完整个项目我最直观的感受是离线语音助手在树莓派上的可行性比大多数人想象的要高很多。现代语音模型的推理效率已经非常高树莓派4B这个级别的设备也能流畅完成实时的中文语音识别和语音合成延迟完全可以接受。几个实操下来最重要的经验值得单独拎出来提醒音频采样率是最容易忽略的坑。很多人模型加载没问题、代码也没问题最后卡在采样率不匹配上识别结果始终不对。优先检查这个环节。树莓派的供电质量直接影响外接USB设备的稳定性。一个高规格的电源能省掉大量排查时间。模型选型不要贪大。树莓派上跑big model识别准确率也许高一点点但延迟和资源占用得不偿失小模型的体验反而更好。systemd自启脚本里一定要加Restartalways语音助手长时间运行保不齐什么时候音频设备掉一下自动重启能省很多心。如果手里正好有一块吃灰的树莓派花一个下午把离线语音助手搭起来你就能拥有一个完全属于自己、不依赖云服务的声控助手。这个体验和用手机语音助手是完全不一样的。