这次我们集中看一个边缘硬件上的完整语音链路:在 reComputer Mini 上,把语音识别(ASR)、本地大模型(LLM)、语音合成(TTS)三段式流水线全部放到离线环境里跑通。
先解释一下为什么要关注这个组合。reComputer Mini 是 Seeed Studio 基于 NVIDIA Jetson 平台推出的边缘 AI 单板计算机,它的特点是体积小、功耗低、自带 GPU 计算能力。云端的语音助手已经很成熟,但很多场景确实不适合把录音传到云端:会议内容的隐私性、车载环境下的网络稳定性、车间仓库的断网要求,都让"本地语音助手"这个方向有实际价值。正因为语音数据的敏感性,离线方案天然多了一层数据安全优势——录音不出设备,网络断开也能对话。
这次要讲的链路非常清晰:
- ASR:用 sherpa-onnx 做离线语音识别,把麦克风输入或音频文件转成文本;
- LLM:用 llama.cpp 启动本地大模型推理服务,提供一个 OpenAI 兼容的 HTTP 接口;
- TTS:再用 sherpa-onnx 做离线语音合成,把大模型回复的文本转成语音。
三个环节都能独立替换,也可以组合成一条完整的语音交互流水线。本文会从环境准备开始,一步一步完成安装部署、功能测试、链路联调、API 封装和批量任务,最后给出一份常见问题排查表。如果你手里正好有一块 Jetson 设备,可以直接照着流程跑一遍;就算设备不一样,这套 ASR → LLM → TTS 的编排思路也有很强的参考价值。
硬件门槛上,内存建议 8GB 以上。reComputer Mini 常见配置有 8GB 和 16GB 版本,8GB 跑 3B 级量化 LLM 比较从容,16GB 可以尝试更大的模型。如果设备只有 4GB 内存,就需要把 LLM 换成 1B 级别的轻量模型,ASR 和 TTS 也要选更小的 ONNX 模型。本文不追求跑一个多大的模型,重点是把"能听、能想说、能说话"的最小闭环跑通。LLM 推理在边缘设备上本身就是最大瓶颈,不要指望它达到云端的回答质量。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 离线语音助手完整链路(ASR + LLM + TTS) |
| 运行平台 | reComputer Mini(NVIDIA Jetson 系列边缘 AI 单板计算机) |
| ASR 引擎 | sherpa-onnx,离线语音识别,支持中文/英文等多语种模型 |
| TTS 引擎 | sherpa-onnx,离线文字转语音,支持中文 VITS 音色模型 |
| LLM 引擎 | llama.cpp 或其他本地推理框架,推荐 Qwen2.5、Phi 系列小参数模型 |
| 硬件门槛 | 内存 8GB 以上更从容;4GB 需选用轻量模型 |
| 是否依赖云服务 | 否,全链路离线运行 |
| 启动方式 | 命令行启动 + Python 编排脚本 |
| 接口能力 | 可封装为 HTTP API,供局域网设备调用 |
| 批量任务 | 支持批量语音识别、批量文本合成 |
| 适合场景 | 离线语音交互、智能家居语音入口、车载语音助手、工业现场语音指令 |
从能力速览能看出来,这套方案的目标不是做一个比肩云端的智能助理,而是把三段式语音链路在受限的硬件上跑通。ASR、LLM、TTS 的模型选择决定了最终效果的下限和上限:识别准不准、回复有没有逻辑、合成声音自然不自然,都取决于你选了什么模型。
因此,文章后面的内容会尽量把每一段拆开来讲。这样你可以在部署时单独替换任意一个环节,例如把 ASR 从 sherpa-onnx 换成其他引擎,或者把 LLM 从 Qwen2.5 换成 Phi-3,而不需要重写整个链路脚本。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 适用场景与使用边界
2.1 适合谁用
第一类是做边缘 AI 产品验证的开发者。很多人手里有 Jetson 开发板,但缺少一个完整的示例项目把语音链路组织起来。这篇文章给出的流程可以直接当作起点。第二类是数据隐私敏感的办公或家庭场景。会议记录、家庭语音备忘这类应用,语音数据留在本地远比上传云端安心。第三类是网络不稳定的工业或户外场景,比如仓库、车间、施工点,离线语音助手可以完成简单的指令交互。第四类是做课程项目或原型验证的学生和研究者,用开源组件组合出一个可用的系统,成本很低。
2.2 不适合什么场景
不适合高并发对话。单块 Jetson 设备的算力有限,如果同时接入多个用户,LLM 推理会排队,体验会明显下降。不适合专业级语音合成。sherpa-onnx 的 TTS 模型自然度不错,但在情感表达、口音控制上和云端商业 TTS 有差距。不适合需要频繁更新知识的场景。本地模型的知识在训练时已经固定,不像云端 API 能接入实时检索。不适合对识别准确率要求极高的嘈杂环境。边缘 ASR 在强噪声场景下的表现需要提前测试,不能默认和云端效果一样。
2.3 合规与安全边界
语音采集是敏感能力,这一点必须明确。不管部署在什么场景,都应当做到:只采集用户主动授权范围内的语音数据;不在未经同意的场景录音;如果涉及对特定人物音色的模拟,必须获得本人授权;不要把离线语音助手用于窃听、诈骗或其他非法用途。
模型权重本身也涉及许可证问题。开源社区下载的模型通常带有 License,商用前要确认是否允许商用和再分发;第三方下载的模型更需要核实来源。建议在项目目录中保留模型来源、版本和许可证说明,方便后续审查。
3. 环境准备与前置条件
3.1 设备与系统准备
reComputer Mini 出厂通常预装 JetPack 系统,内含 CUDA、cuDNN、TensorRT 等 NVIDIA 组件。如果拿到的是新板子,先确认系统能否正常启动,再确认 JetPack 版本。不同版本的 JetPack 对应不同版本的 CUDA,后续安装 onnxruntime 或构建 llama.cpp 时要注意版本匹配。开始部署前,用以下命令确认硬件状态:
bash复制# 查看 Jetson 设备信息和当前状态
sudo nvcc --version
sudo tegrastats --interval 1000 --once
tegrastats 会输出 CPU、GPU、内存、功耗等信息。如果看到内存只有 4GB,优先选择更小体积的模型;8GB 以上内存跑 3B 级 LLM 更从容。同时确认系统盘剩余空间,建议至少预留 10GB 以上,因为模型文件、依赖库、日志和临时文件都会占空间。
供电也要留意。LLM 推理时整机功耗会明显上升,使用原装电源更稳妥,如果供电不足,设备可能出现随机重启或降频。建议在部署前先做一个简单的负载测试,确保设备能在高负载下稳定运行。
3.2 系统与 Python 环境
在正式安装依赖之前,先确认系统状态:
bash复制# 查看系统版本和 Python 版本
cat /etc/nv_tegra_release
python3 --version
sudo apt update
建议使用 Python 3.10 或 3.11,并用虚拟环境隔离依赖。不要直接在系统 Python 里安装大量 pip 包,否则后续其他项目可能出现依赖冲突。本方案需要以下组件:
| 组件 | 用途 |
|---|---|
| sherpa-onnx | ASR 和 TTS 的推理引擎 |
| numpy | 音频数据处理 |
| soundfile | 读写 WAV 文件 |
| fastapi + uvicorn | 封装 HTTP API 服务 |
| requests | 调用本地 LLM 的 HTTP 接口 |
| llama.cpp | 本地 LLM 推理框架 |
这些组件里,sherpa-onnx 和 llama.cpp 是核心,需要在设备上单独验证安装;其他 Python 包在虚拟环境里用 pip 安装即可。
3.3 音频输入输出准备
链路中的 ASR 需要音频输入。测试阶段建议先用 WAV 文件,这样不需要额外音频硬件,也方便批量测试。如果要做实时麦克风语音助手,需要准备 USB 麦克风或板载音频输入,并确认设备能被系统识别:
bash复制# 查看系统是否识别到音频采集设备
arecord -l
更稳妥的做法是先用文件输入跑通链路,再接麦克风做实时输入。实时采集会增加很多边界问题,比如静音检测、端点检测、声道转换、采样率统一。先保留文件输入可以减少变量,链路稳定后再逐步增加实时性能力。
3.4 模型选择建议
ASR 模型优先选择 sherpa-onnx 官方仓库的中文语音识别模型,ONNX 格式,配套 tokens.txt 文件。LLM 模型建议选择 GGUF 格式,这是 llama.cpp 支持的模型格式,体积比原始权重小很多。Qwen2.5-3B-Instruct 这类模型在 8GB 内存设备上可以运行。TTS 模型选择 sherpa-onnx 官方提供的 VITS 中文音色模型,同样需要 model.onnx 和 tokens.txt。初次验证统一选用 q4 量化版本,速度和内存占用更可控。
4. 安装部署与启动方式
4.1 创建虚拟环境
bash复制mkdir -p ~/voice-assistant
cd ~/voice-assistant
python3 -m venv venv
source venv/bin/activate
虚拟环境创建后,后续所有 pip 安装都在这个环境中执行。如果机器上已经存在其他 Python 项目,这样的隔离能避免版本冲突。
4.2 安装 Python 依赖
bash复制pip install --upgrade pip
pip install sherpa-onnx numpy soundfile
pip install fastapi uvicorn requests
如果 sherpa-onnx 在 Jetson 上没有直接可用的预编译包,pip 会尝试从源码编译,这个过程需要耐心等待。安装完成后,用简单命令验证导入是否正常:
bash复制python -c "import sherpa_onnx; print(sherpa_onnx.__version__)"
如果不能成功导入,不要继续跑后面的链路脚本。先解决安装问题,否则后面所有 Python 脚本都会在 import sherpa_onnx 处报错。
4.3 下载并放置模型文件
模型文件的目录结构建议如下:
bash复制mkdir -p models/asr models/llm models/tts
下载完成后,把 ASR 模型文件放入 models/asr,LLM 的 GGUF 文件放入 models/llm,TTS 模型放入 models/tts。不同模型的下载方式不同,建议写一个 download.sh 记录下载源和版本号,方便后续复现。模型文件体积较大,下载耗时取决于网络环境,不要在下载过程中中断。如果出现文件不完整,运行时会有明确报错。
4.4 启动本地 LLM 服务
LLM 服务是整条链路中唯一需要长时间运行的进程。以下命令是 llama.cpp 启动 HTTP 服务的通用写法,实际二进制路径和模型路径需要根据你的编译目录调整:
bash复制./build/bin/llama-server \
-m /path/to/qwen2.5-3b-instruct-q4_k_m.gguf \
-c 2048 \
--host 127.0.0.1 \
--port 8080
参数说明:
-m:模型文件路径;-c:上下文长度,2048 对边缘设备比较合适;--host:只监听本机;--port:HTTP 服务端口。
启动后,用 curl 验证服务是否正常:
bash复制curl http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model": "local", "messages": [{"role": "user", "content": "你好"}]}'
如果返回 JSON 响应,说明 LLM 服务已经就绪。如果 curl 卡住,多半是模型还在加载,多等几秒再试。如果端口被占用,需要先用 lsof 查看占用情况,然后换一个端口启动。
5. 功能测试与效果验证
5.1 ASR 识别测试
准备好一段 16kHz 采样率的中文语音 WAV 文件,命名为 hello.wav,放到项目根目录。然后运行以下测试脚本:
python复制# test_asr.py
import sherpa_onnx
import soundfile as sf
recognizer = sherpa_onnx.OfflineRecognizer.from_onnx(
model="models/asr/model.onnx",
tokens="models/asr/tokens.txt",
num_threads=2,
provider="cpu",
sample_rate=16000,
feature_dim=80,
)
samples, sample_rate = sf.read("hello.wav", dtype="float32")
stream = recognizer.create_stream()
stream.accept_waveform(sample_rate, samples)
recognizer.decode_stream(stream)
print(stream.result.text)
这段代码是 sherpa-onnx 的通用调用方式。不同的模型包可能要求不同的 feature_dim,如果提示错误,需要查模型的说明文档。判断识别是否成功的标准很简单:输出的文字和录音内容一致。
如果识别不准,按以下顺序排查:
- 音频采样率是不是 16kHz;
- 录音中是否有明显噪声;
- 模型是不是面向中文的 ASR 模型;
- tokens.txt 是否和模型来自同一个发布版本。
5.2 TTS 合成测试
TTS 部分同样用独立脚本验证:
python复制# test_tts.py
import sherpa_onnx
import soundfile as sf
tts_config = sherpa_onnx.OfflineTtsConfig(
model=sherpa_onnx.OfflineTtsModelConfig(
vits=sherpa_onnx.OfflineTtsVitsModelConfig(
model="models/tts/model.onnx",
tokens="models/tts/tokens.txt",
),
num_threads=2,
),
)
tts = sherpa_onnx.OfflineTts(tts_config)
samples = tts.generate("你好,欢迎使用本地语音助手。", sid=0, speed=1.0)
if len(samples.samples) > 0:
sf.write("output.wav", samples.samples, samples.sample_rate)
print("输出文件: output.wav")
else:
print("合成失败")
生成的 output.wav 应该能正常播放且语音清晰。如果出现无声音或明显噪声,优先检查 model.onnx 和 tokens.txt 是否匹配。同一个模型的这两个文件必须来自同一发布版本,混用会导致音素映射错乱,合成结果会是乱码或杂音。
5.3 LLM 对话测试
LLM 部分已经在第 4 章通过 curl 验证过。在链路编排里,LLM 统一通过 HTTP 接口调用,这是刻意的设计选择。这样做的好处是:LLM 服务独立于 Python 进程运行,ASR 和 TTS 脚本重载时不会把模型重新加载一遍;以后想换聊天模型,只需要修改启动命令,链路代码完全不用动。
调用本地 LLM 时,可以设置一个较长的超时时间。边缘设备上的首轮请求可能包含模型上下文初始化,耗时比后续请求更长。如果链路脚本中把超时设得太短,就会出现偶发的"LLM 超时但服务其实正常"的误判。
5.4 链路联调测试
当三个组件各自验证通过后,把三部分串成一条完整链路。这一步是整个项目的核心,也是最容易出问题的地方:
python复制# pipeline.py
import soundfile as sf
import requests
import sherpa_onnx
recognizer = sherpa_onnx.OfflineRecognizer.from_onnx(
model="models/asr/model.onnx",
tokens="models/asr/tokens.txt",
num_threads=2,
provider="cpu",
sample_rate=16000,
feature_dim=80,
)
tts_config = sherpa_onnx.OfflineTtsConfig(
model=sherpa_onnx.OfflineTtsModelConfig(
vits=sherpa_onnx.OfflineTtsVitsModelConfig(
model="models/tts/model.onnx",
tokens="models/tts/tokens.txt",
),
num_threads=2,
),
)
tts = sherpa_onnx.OfflineTts(tts_config)
LLM_URL = "http://127.0.0.1:8080/v1/chat/completions"
def asr_to_text(audio_path):
samples, sample_rate = sf.read(audio_path, dtype="float32")
stream = recognizer.create_stream()
stream.accept_waveform(sample_rate, samples)
recognizer.decode_stream(stream)
return stream.result.text.strip()
def ask_llm(question):
payload = {
"model": "local",
"messages": [{"role": "user", "content": question}],
}
response = requests.post(LLM_URL, json=payload, timeout=120)
return response.json()["choices"][0]["message"]["content"]
def tts_speak(text, output_path):
samples = tts.generate(text, sid=0, speed=1.0)
if len(samples.samples) > 0:
sf.write(output_path, samples.samples, samples.sample_rate)
return output_path
if __name__ == "__main__":
question = asr_to_text("hello.wav")
print("ASR 识别结果:", question)
answer = ask_llm(question)
print("LLM 回答:", answer)
tts_speak(answer, "answer.wav")
print("TTS 音频已生成: answer.wav")
运行链路脚本时,第一次联调的关键是观察日志。ASR 输出是否为空、LLM 是否超时、TTS 是否生成文件,三个环节可以分别用日志标记时间点,帮助定位瓶颈。如果 LLM 请求超时,回到第 4 章单独启动服务并验证接口,不要在整个链路里反复猜测。
链路联调还有一个容易被忽略的细节:ASR 识别出来的文本可能有标点缺失或空格问题。直接把 ASR 输出拼接进 LLM 提示词通常没问题,但如果识别结果过短或包含明显的停顿噪声符号,LLM 的回答质量会明显下降。可以在 asr_to_text 返回值上做一次简单的清理,去掉空白和特殊字符。
6. 接口 API 与批量任务
6.1 封装 HTTP API
链路跑通后,用 FastAPI 把入口封装成 POST 接口。其他设备只需要向接口提交音频文件,就能拿到返回的语音回复文件。下面是 app.py 的完整示例:
python复制# app.py
from fastapi import FastAPI, File, UploadFile
from fastapi.responses import FileResponse
import tempfile
import os
import pipeline
app = FastAPI()
@app.post("/voice")
async def voice_in(file: UploadFile = File(...)):
suffix = os.path.splitext(file.filename)[-1]
tmp_input = tempfile.NamedTemporaryFile(delete=False, suffix=suffix)
tmp_input.write(await file.read())
tmp_input.close()
question = pipeline.asr_to_text(tmp_input.name)
answer = pipeline.ask_llm(question)
output = tempfile.NamedTemporaryFile(delete=False, suffix=".wav")
pipeline.tts_speak(answer, output.name)
os.unlink(tmp_input.name)
return FileResponse(output.name, media_type="audio/wav")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
启动服务:
bash复制uvicorn app:app --host 0.0.0.0 --port 8000
调用测试:
bash复制curl -X POST http://127.0.0.1:8000/voice \
-F "file=@hello.wav" \
-o response.wav
这里有两个容易踩的坑。第一,--host 0.0.0.0 意味着局域网内任何设备都能访问这个接口,如果只做本机测试,改成 127.0.0.1 更安全。第二,每次请求都会生成临时文件和新的 TTS 音频,长时间运行后需要定期清理临时目录,否则磁盘会被占满。生产环境应该增加鉴权机制,例如令牌校验或请求签名,避免接口被未授权调用。
6.2 批量任务设计
批量任务在语音助手的开发中非常实用。常见的有两类:批量语音识别和批量文本合成。
批量语音识别的思路是准备一个 inputs 目录,放入多个 WAV 文件,循环读取并调用 ASR 识别,把结果写入汇总文本或 CSV。批量文本合成类似,准备一个文本文件,每行一条待合成内容,循环调用 TTS,按行号命名输出 WAV 文件。
python复制import glob
import os
import pipeline
audio_dir = "inputs"
for path in sorted(glob.glob(os.path.join(audio_dir, "*.wav"))):
try:
text = pipeline.asr_to_text(path)
print(f"{path}: {text}")
except Exception as e:
print(f"{path}: FAILED - {e}")
批量任务最重要的不是跑得多快,而是稳定。边缘设备内存有限,长时间循环可能因为资源未释放而出问题。建议在批量任务中做到:每个文件处理完后清理不必要的大对象;捕获所有异常且不中断整个队列;定期输出进度日志;如果连续多次失败则主动停止任务,避免无效重试浪费资源。
7. 资源占用与性能观察
7.1 用 tegrastats 观察资源占用
Jetson 平台自带 tegrastats 工具,可以实时观察 CPU、GPU、内存、功耗和温度:
bash复制tegrastats --interval 5
观察重点有三个。第一,GPU 占用是否在推理时明显上升。如果没有明显变化,说明模型实际跑在 CPU 上,需要检查 onnxruntime 是否启用了 CUDA。第二,内存是否在多个任务后持续增长。如果持续增长,说明代码里有资源没有被释放,需要排查。第三,温度是否长时间超过 80 摄氏度。温度过高时 Jetson 会主动降频,推理速度会明显下降。
7.2 推理延迟分布
整条链路的延迟由 ASR、LLM、TTS 三部分组成。ASR 延迟主要取决于音频长度和模型大小;LLM 延迟取决于模型参数量、上下文长度和是否流式输出,在边缘设备上通常是最大瓶颈;TTS 延迟取决于文本长度和合成引擎效率。
如果回答环节明显卡顿,优先考虑减少 LLM 上下文长度,或者换用更小参数的量化模型。ASR 和 TTS 的影响相对较小,但也不要把采样率调得过高。对语音识别来说,16kHz 已经足够,44.1kHz 的音频对识别准确率没有明显帮助,反而会增加处理延迟。
7.3 降低资源占用的方法
只加载一个 ASR 模型实例,不要重复创建 recognizer 对象。重复创建模型对象不仅浪费内存,还会拖慢整个脚本的启动速度。LLM 服务的线程数不要设置过高,--threads 控制在合理范围内,过多线程反而会因为调度开销降低效率。TTS 合成用 num_threads=2 通常已经足够,不需要多线程。
长文本合成时,可以提前把文本切分成短句,逐句合成后再拼接音频文件。这样做的好处是当某一句合成失败时,不会影响前面的结果。批量任务中,每个任务之间加一两秒短暂 sleep,给设备降温和释放内存的时间。
8. 常见问题与排查方法
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 启动链路脚本报错找不到模型 | 模型路径错误 | 检查 models 目录和代码路径 | 修正路径或复制模型文件 |
| ASR 识别结果为空 | 音频采样率不是 16kHz | 用 soundfile 检查采样率 | 重采样为 16kHz |
| LLM 接口请求超时 | LLM 服务未启动或仍在加载 | 单独 curl 验证接口 | 确认 llama-server 就绪后再调用链路 |
| TTS 生成文件无法播放 | model.onnx 与 tokens.txt 不匹配 | 检查模型来源和版本 | 从同一版本重新下载 |
| GPU 占用率很低 | 模型实际上跑在 CPU | 检查 provider 参数 | 安装 CUDA 版 onnxruntime 或用 cuda provider |
| 批量任务中途卡死 | 内存膨胀或资源未释放 | 观察 tegrastats 日志 | 增加异常捕获和资源清理 |
| 端口被占用 | 8080 或 8000 被其他进程占用 | sudo lsof -i :8080 |
换端口或终止占用进程 |
遇到问题时,建议按照"先确认基础环境,再逐步隔离环节"的原则排查。比如链路完全不通时,先跑 python -c "import sherpa_onnx" 确认依赖正常;ASR 输出异常时,单独跑 test_asr.py;LLM 不响应时,单独用 curl 测试接口。这种分段排查方式比从头到尾看流水日志高效得多。
如果 ASR 单独测试正常但在链路脚本中失败,常见原因是代码里的 recognizer 对象被重新创建,或者输入的音频文件路径错误。如果 TTS 单独测试正常但在链路脚本中生成的音频过短,可能是 LLM 返回了空文本或截断的输出。这些问题都可以通过打印中间日志快速定位。
9. 最佳实践与使用建议
9.1 目录管理
模型文件、输入素材、输出结果、日志建议分开存放:
text复制voice-assistant/
├── models/
│ ├── asr/
│ ├── llm/
│ └── tts/
├── inputs/
├── outputs/
├── logs/
├── venv/
├── download.sh
└── pipeline.py
模型体积大且不需要频繁变动,输入素材可以随时清理,输出结果按时间归档,日志保留最近几天的即可。这样组织后,即使出现磁盘空间告警,也能快速判断哪些文件可以安全删除。
9.2 工程化建议
第一次先小参数模型跑通,再切换到目标模型。保留一套最小可运行配置,方便回退。模型下载脚本要记录来源和版本,方便复现。批量任务增加日志和失败重试机制,API 服务增加简单鉴权。涉及人脸、声音、版权素材时,必须确认授权。发布商用产品前,对 LLM 的输出做效果复核,必要时增加内容安全过滤层。
在 reComputer Mini 这类设备上开发,还要注意散热和长期运行稳定性。如果设备放在封闭机箱里,LLM 推理产生的热量会持续累积,建议观察设备在持续负载下的温度表现,必要时增加散热措施或降低 LLM 的线程数。
9.3 数据合规建议
模型权重来自开源社区时,保留对应的 License 文件;录音前获得用户明确授权;不要在敏感场所即插即用语音助手;发布商用产品前,评估模型输出内容是否存在偏见或诱导风险,必要时加内容安全过滤层。这些不是可选项,而是语音类产品的基本工程要求。
10. 总结与下一步
这套方案最有价值的点是:在 reComputer Mini 这种受限边缘设备上,用开源组件把 ASR → LLM → TTS 三段链路完整跑通,并且实现了接口化和批量化的基本能力。拿到这篇流程后,第一件事是用一段中文 WAV 音频跑通最小闭环,验证 ASR 识别、LLM 回答、TTS 合成三个环节都能正常工作。
最容易踩的坑有三个:模型路径不一致、音频采样率不匹配、LLM 服务没有提前启动。这三个问题在动手前检查一遍,能省下大量排查时间。尤其是 LLM 服务,它需要在链路脚本运行之前完成启动,否则第一次调用就会遇到连接失败或超时。
后续扩展方向也比较明确:接入麦克风做实时唤醒,增加端点检测和 VAD;把 TTS 音色切换做成配置文件;把 LLM 从纯文本对话升级为工具调用模式;甚至可以把整条链路打包进 Docker 镜像,方便在更多 Jetson 设备上复现。如果你手里正好有 reComputer 或类似的 Jetson 设备,建议先收藏这篇流程,按顺序跑一遍最小闭环,跑通后再逐步加功能。
