作者:李伟斌 AKA 漂移菌
前言
在一个机缘巧合下,我得到了一个超可爱的神器, clawbox, 我选择的颜色是猛男粉,可能搞技术的最后内心最深处还是喜欢那一抹粉色的小可爱吧。完整教程在后面,可以直接往下拉,直接进入教程。
先给你们展示一下这个设备的外观:小盒子非常小巧,比我想象中小很多。
拆看看看,记得从这里下手,比较有仪式感。
包裹的非常结实,稳稳当当的。
首先你看到的是它的天线, 按我 对上海晶珩 ED-CLAWBOX(“龙虾盒子”)的 理解:图上这根应是随机的外置 Wi‑Fi/蓝牙胶棒天线。官方资料能确认的是:包装含 1× 2.4GHz/5GHz Wi‑Fi/BT Antenna,机身侧板有 1× SMA 天线座;无线规格为 2.4G 802.11 b/g/n、5G 802.11 a/n/ac,蓝牙 2402–2480MHz。
第三方安装指南也称它为 SMA 双频胶棒天线。天线怼这里,记得拧紧。记得要接入天线后再上电,不要不带天线就开机。
关键点:官方没有公布这根天线的 dB/dBi 增益,所以不能可靠断言它是 3dB、5dB 还是别的。天线增益更规范的写法通常是 dBi(相对理想点源),dBi = dBd + 2.15。
从形态看,它是短小全向胶棒天线,不是高增益定向天线;这类双频 Wi‑Fi/BT 天线常见大约在 2–3 dBi 量级,但这只是经验范围,不是 ED-CLAWBOX 官方参数,我在系统里只能简单测试一下:
# 1) 看无线接口名,可能是 wlan0 / wlan1ip linkiw dev# 2) 看当前连接状态:信号、速率、发射功率iw dev wlan0 linkiwconfig wlan0
重点看signal: -xx dBm 、 tx bitrate 、 rx bitrate 、 txpower 。一般 RSSI 越接近 0 越好; -45dBm 通常很好, -70 dBm 偏弱, -80 dBm` 以下容易不稳。
剩下就是主体了:
左到右: USB-C口,FULLSIZE HDMI口, Micro HDMI口, TF卡槽,里面已经有烧录好系统的卡,非常nice!
这里有个黑色的USB2.0, 两个USB3.0(蓝色), 一个千兆以太网口,都是CM5 的接口引出来的,还有一个3.5mm 耳机接口,接个耳机或者有源音箱也可以完成下面的项目,但是,我是说但是,它竟然还有内置喇叭。。。
我上面所说的 Clawbox 就是 ED-CLAWBOX「龙虾盒子」——上海晶珩(EDATEC)基于树莓派 CM5 做的端侧 AI 小主机,一般搭载 16GB 内存 + CM5 的 BCM2712 四核 Cortex-A76 @2.4GHz,不过我拿到的是一个4GB内存的版本,存储是MicroSD卡,64GB大小,采用的核心是树莓派CM5 Lite版本,就是不带eMMC的版本!
给你们看看带eMMC的版本哈哈
不过是修复版。
好了,到这里就介绍完外观了,这时候为了让它算力加强50%,必须补贴纸。哈哈,好看吧?ok,言归正传,我们进入今天的主题。
按照我的理解,这套硬件跑 llama.cpp + 本地 TTS 完全可行,下面给你一套完整可落地的方案。
一、前期准备
# 确认是 64 位系统(必须)uname -m # 应输出 aarch64cat /etc/os-release# 系统依赖sudo apt updatesudo apt install -y build-essential cmake git pkg-configlibcurl4-openssl-dev python3-pip python3-venv
建议把模型放 NVMe 或高速 SD 卡上,模型加载会明显更快。我决定本地操作。
二、编译 llama.cpp(针对 BCM2712 优化)
git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp
建议固定一个 release tag,保证可复现
git clone https://github.com/ggml-org/llama.cpp.gitcd llama.cpp# 建议固定一个 release tag,保证可复现git checkout $(git describe --tags --abbrev=0)cmake -B build -DCMAKE_BUILD_TYPE=Release-DGGML_NATIVE=ON-DLLAMA_CURL=ONcmake --build build --config Release -j"$(nproc)"
CM5 的 A76 支持 ARMv8.2 的 dotprod 和 fp16 指令, -DGGML_NATIVE=ON 让编译器自动启用这些 SIMD 优化,对矩阵乘性能影响显著, 整个编译在 CM5 上大约需要 10–20 分钟。这时候就点杯瑞幸摸摸鱼。
三、挑选 GGUF 模型
经验法则(Q4_K_M 量化):
社区实测 CM5 16GB 跑 3B 模型约 5 t/s、占 4–5GB 内存,7B 级别可用但要有耐心。做中文语音助手推荐 Qwen2.5-3B/7B-Instruct,中文能力强
下载(国内建议先用 export HF_ENDPOINT=https://hf-mirror.com ):
mkdir -p ~/models && cd ~/models# 以 Qwen2.5-7B-Instruct 的 Q4_K_M 为例,3B 版把 7B 换成 3Bwget "https://hf-mirror.com/Qwen/Qwen2.5-7B-Instruct-GGUF/resolve/main/qwen2.5-7b-instruct-q4_k_m.gguf"
四、跑起来:llama-server 提供 OpenAI 兼容 API
./build/bin/llama-server-m ~/models/qwen2.5-7b-instruct-q4_k_m.gguf-t 4 -c 4096--mlock--host 0.0.0.0 --port 8080
调优要点(都是在 Pi 上实测有效的经验):
-t 4 :四个核跑满;线程不是越多越好,跑一下 llama-bench -t 1,2,4
--mlock :把模型页锁在内存里防止被换出;前提是模型确实装得下内存
散热:Clawbox 是无风扇铝合金机身,问题不大,但满载跑了很久后可以 vcgencmd get_throttled 检查有没有降频
想常驻就写个 systemd service,设 Restart=on-failure 即可。
这里后面会出各种问题,所以你们先作为开胃菜先了解一下,不要纠结参数了。后面有详细讲解。
五、文字转语音:Piper(中文离线 TTS)
lama.cpp 只管文本,TTS 推荐 Piper——它就是冲着树莓派优化的本地神经 TTS,ONNX 格式、CPU 推理极快,中文有现成的 zh_CN-huayan-medium 模型。
我参考这里的:piper-tts | 阿超
https://vampireachao.github.io/2024/12/15/piper-tts/index.html#:~:text=Piper%E9%92%88%E5%AF%B9Raspberry%20Pi%204%E8%BF%9B%E8%A1%8C%E4%BA%86%E4%BC%98%E5%8C%96%EF%BC%8C%E5%8D%B3%E4%BD%BF%E5%9C%A8%E4%BD%8E%E6%80%A7%E8%83%BD%E7%A1%AC%E4%BB%B6%E4%B8%8A%E4%B9%9F%E8%83%BD%E5%AE%9E%E7%8E%B0%E9%AB%98%E8%B4%A8%E9%87%8F%E8%AF%AD%E9%9F%B3%E5%90%88%E6%88%90%E3%80%82%20%C2%B7%20%E5%A4%9A%E8%AF%AD%E8%A8%80%E6%94%AF%E6%8C%81%EF%BC%9A%E6%94%AF%E6%8C%81%E8%B6%85%E8%BF%8730%E7%A7%8D%E8%AF%AD%E8%A8%80
pip install piper-tts # 会自动带 onnxruntimemkdir -p ~/piper_models && cd ~/piper_models# 两个文件都要下:.onnx 模型 + .onnx.json 配置wget https://hf-mirror.com/rhasspy/pipervoices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnxwget https://hf-mirror.com/rhasspy/pipervoices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx.json
测试一条:
echo "你好,我是龙虾盒子。" | piper--model ~/piper_models/zh_CN-huayan-medium.onnx--output-raw | aplay -r 22050 -f S16_LE -t raw -
哈哈,是不是没有声音?这里你肯定要翻车,原因是什么?你会发现默认输出设备还没有配置,各种坑都踩一遍你才知道,所以这里先卖个关子,你是不是内里都开始刺挠了?哈哈,我也是,别着急,继续看,后面有整理的完整版。哈哈
这里要说一个问题,就是关于内存限制的部分,我专门用了点儿时间分析了一下4GB内存对于整个项目的约束。
4GB 的现实约束
系统本身(Raspberry Pi OS + 后台服务)占掉约 0.6–1GB,实际能给模型用的只有约 2.5–3GB
模型权重 + KV cache + llama-server 进程开销都要算进去
Clawbox 预装的 JishuShell 面板也会常驻占内存,可以 systemctl stop jishushell 在跑推理时关掉,或者干脆留着(它不算太重)今天还遇到一个群友的jishushell更新了重启系统卡死了。
好了,中间遇到各种麻烦,我都一一解决了,花费了好久,终于搞定了,我知道你们也已经按耐不住要扔主板丢我了,我还是赶紧直接请出保姆级教程步骤吧
正片开始:树莓派 CM5 (4GB) 本地语音助手搭建教程
适用设备:ED-CLAWBOX「龙虾盒子」(树莓派 Compute Module 5,4GB 内存,板载 WM8960 声卡) 目标:完全离线的「语音对话」—— 麦克风录音 → 本地语音识别 → 本地大语言模型(Qwen GGUF) → 本地语音合成播报 全部组件:llama.cpp + Qwen2.5-1.5B(GGUF) + faster-whisper(STT) + Piper(TTS)
作者: 李伟斌 AKA 漂移菌
一、硬件与总体架构
你说话 --> WM8960 麦克风|vfaster-whisper (base, int8) <-- 语音识别 STT|vllama-server (Qwen2.5-1.5B GGUF) <-- 大语言模型, OpenAI 兼容 API :8080|vPiper (zh_CN-huayan-medium) <-- 语音合成 TTS|vWM8960 扬声器 / HDMI
4GB 内存分配预算(实测稳定):
二、系统准备
# 确认 64 位系统(必须)uname -m # 应输出 aarch64# 系统依赖sudo apt updatesudo apt install -y build-essential cmake git pkg-configlibcurl4-openssl-dev python3-pip python3-venv# 建议将模型放在 NVMe / 高速 SD 卡上,加载更快
4GB 内存机器务必开启 zram 交换(防 OOM):
sudo apt install -y zram-toolsecho 'ALGO=zstd' | sudo tee -a /etc/default/zramswapecho 'PERCENT=50' | sudo tee -a /etc/default/zramswap # 2GB zramsudo systemctl restart zramswapfree -h # 确认 Swap 列出现 ~2G
国内网络建议先设置镜像:
export HF_ENDPOINT=https://hf-mirror.com # HuggingFace 镜像,下载模型用echo 'export HF_ENDPOINT=https://hf-mirror.com' >> ~/.bashrc
三、编译 llama.cpp
git clone https://github.com/ggml-org/llama.cpp.gitcd llama.cppgit checkout $(git describe --tags --abbrev=0) # 固定 release 版本cmake -B build -DCMAKE_BUILD_TYPE=Release-DGGML_NATIVE=ON-DLLAMA_CURL=ONcmake --build build --config Release -j"$(nproc)"
说明:
CM5 的 Cortex-A76 支持 ARMv8.2 dotprod / fp16 指令, -DGGML_NATIVE=ON 自动启用 SIMD 优化,对推理速度影响显著
编译在 CM5 上约需 10–20 分钟
四、下载 GGUF 模型(4GB 内存的选择)
推荐 Qwen2.5-1.5B-Instruct Q4_K_M(权重约 1.0GB,CM5 上约 8–12 t/s)
mkdir -p ~/models && cd ~/modelswget "https://hf-mirror.com/Qwen/Qwen2.5-1.5B-Instruct-GGUF/resolve/main/qwen2.5-1.5binstruct-q4_k_m.gguf"
五、运行 llama-server
./build/bin/llama-server-m ~/models/qwen2.5-1.5b-instruct-q4_k_m.gguf-t 4 -c 2048--cache-type-k q8_0 --cache-type-v q8_0--host 0.0.0.0 --port 8080
看到 server is listening on http://0.0.0.0:8080 即成功。测试:
curl http://127.0.0.1:8080/v1/chat/completions-H "Content-Type: application/json"-d '{"messages":[{"role":"user","content":"你好,你是谁?"}],"max_tokens":100}'
常驻化(systemd): 可选,新建 /etc/systemd/system/llama.service :
[Unit]Description=llama.cpp serverAfter=network.target[Service]User=piExecStart=/home/pi/llama.cpp/build/bin/llama-server-m /home/pi/models/qwen2.5-1.5b-instruct-q4_k_m.gguf-t 4 -c 2048 --cache-type-k q8_0 --cache-type-v q8_0--host 127.0.0.1 --port 8080Restart=on-failure[Install]WantedBy=multi-user.target
sudo systemctl enable --now llama
六、安装 Piper TTS(中文语音合成)
pip install piper-tts # 会自动安装 onnxruntimemkdir -p ~/piper_models && cd ~/piper_models# 两个文件都要下载:模型 + 配置wget https://hf-mirror.com/rhasspy/pipervoices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnxwget https://hf-mirror.com/rhasspy/pipervoices/resolve/main/zh/zh_CN/huayan/medium/zh_CN-huayan-medium.onnx.json
Piper 特点:ONNX 格式、CPU 推理极快、针对树莓派优化、支持 30+ 语言,模型仅几十 MB。
七、声卡配置(Clawbox 板载 WM8960)
查看声卡:
aplay -l
典型输出:
card 0: vc4hdmi0 ... # HDMI 0card 1: vc4hdmi1 ... # HDMI 1card 2: wm8960soundcard ... # 板载扬声器 + 麦克风,用这个
测试板载扬声器:
echo "你好,我是千问模型" | piper--model ~/piper_models/zh_CN-huayan-medium.onnx--output-raw | aplay -D plughw:2,0 -r 22050 -f S16_LE -t raw -
要点:采样率必须是 22050Hz(medium 模型的输出采样率,写在 .onnx.json 里),写错会变调。
设为默认声卡(播放 + 采集都指向 card 2):
cat > ~/.asoundrc << 'EOF'defaults.pcm.card 2defaults.ctl.card 2EOF
音量调节:
amixer -c 2 sset 'Speaker' 80% # 播放音量amixer -c 2 sset 'Capture' 70% # 麦克风采集增益
八、文字版助手(先打通链路)
import re, requests, subprocessfrom piper import PiperVoicevoice = PiperVoice.load("/home/pi/piper_models/zh_CN-huayan-medium.onnx")def speak(text):text = re.sub(r"(d)", r" 1 ", text) # 数字加空格,朗读更自然aplay = subprocess.Popen(["aplay", "-r", "22050", "-f", "S16_LE", "-t", "raw", "-"],stdin=subprocess.PIPE)for chunk in voice.synthesize(text):aplay.stdin.write(chunk.audio_int16_bytes) # 边合成边播aplay.stdin.close()aplay.wait()def chat(prompt):r = requests.post("http://127.0.0.1:8080/v1/chat/completions", json={"messages": [{"role": "user", "content": prompt}],"temperature": 0.6, "max_tokens": 200})return r.json()["choices"][0]["message"]["content"]if __name__ == "__main__":while True:q = input("> ")if q in ("exit", "quit"):breakans = chat(q)print(ans)speak(ans)
关键 API 细节: voice.synthesize(text) 返回的是生成器,逐块产出 AudioChunk 对象,不是 numpy 数组。取 PCM 字节用 chunk.audio_int16_bytes ,取 int16 数组用 chunk.audio_int16_array 。
九、语音输入:faster-whisper STT
9.1 验证麦克风
arecord -D plughw:2,0 -f S16_LE -r 16000 -c 1 -d 5 test.wavaplay test.wav
9.2 安装
sudo apt install -y libportaudio2pip install faster-whisper sounddevice webrtcvad-wheels
9.3 最小 STT 测试
from faster_whisper import WhisperModelmodel = WhisperModel("tiny", device="cpu", compute_type="int8", cpu_threads=4)segments, _ = model.transcribe("test.wav", language="zh", beam_size=1)print("识别结果:", "".join(s.text for s in segments))
tiny :快、小,中文偶尔错字
base :中文明显更准,速度稍慢,4GB 机器推荐
9.4 完整双向语音助手 voice_assistant.py
import re, requests, subprocessimport numpy as npimport sounddevice as sdimport webrtcvadfrom faster_whisper import WhisperModelfrom piper import PiperVoiceSAMPLE_RATE = 16000FRAME = 480 # 30ms, webrtcvad 要求的帧长vad = webrtcvad.Vad(2) # 灵敏度 0~3,2 比较稳stt = WhisperModel("base", device="cpu", compute_type="int8", cpu_threads=2)voice = PiperVoice.load("/home/pi/piper_models/zh_CN-huayan-medium.onnx")def listen():# 录音直到说完(约1秒静音自动停止),返回 PCM bytesprint("请讲...", flush=True)frames, silence, triggered = [], 0, Falsewith sd.RawInputStream(samplerate=SAMPLE_RATE, blocksize=FRAME,dtype="int16", channels=1) as s:while True:data, _ = s.read(FRAME)chunk = bytes(data)if vad.is_speech(chunk, SAMPLE_RATE):triggered, silence = True, 0elif triggered:silence += 1if silence > 33: # 约1秒静音 = 说完了breakif triggered:frames.append(chunk)if len(frames) > 330: # 最长10秒,防卡死breakreturn b"".join(frames)def transcribe(pcm):audio = np.frombuffer(pcm, dtype=np.int16).astype(np.float32) / 32768.0segs, _ = stt.transcribe(audio, language="zh", beam_size=1)return "".join(s.text for s in segs).strip()def chat(prompt):r = requests.post("http://127.0.0.1:8080/v1/chat/completions", json={"messages": [{"role": "user", "content": prompt}],"temperature": 0.6, "max_tokens": 200})return r.json()["choices"][0]["message"]["content"]def speak(text):text = re.sub(r"(d)", r" 1 ", text)aplay = subprocess.Popen(["aplay", "-r", "22050", "-f", "S16_LE","-t", "raw", "-"], stdin=subprocess.PIPE)for chunk in voice.synthesize(text):aplay.stdin.write(chunk.audio_int16_bytes)aplay.stdin.close()aplay.wait()if __name__ == "__main__":while True:try:pcm = listen()if not pcm:continueq = transcribe(pcm)print("你说:", q, flush=True)if not q:continueans = chat(q)print("Qwen:", ans, flush=True)speak(ans)except KeyboardInterrupt:break
预期延迟 3–6 秒/轮(主要是 LLM 8–12 t/s 的生成时间)。
调优:
转写慢:把模型名 "base" 换成 "tiny"
误触发/不触发: Vad(2) 调 1(保守)或 3(灵敏);环境吵则把静音帧 33 加大到 50
十、踩坑记录(FAQ)
Q1: invalid argument --no-mmap 新版 llama.cpp(2024 年末起)已移除 --no-mmap ,mmap 加载是默认行为。直接删掉该参数;想防换出就用 --mlock (小内存机器慎用)。
Q2: OSError: PortAudio library not found sudo apt install -y libportaudio2 。或者干脆绕开 sounddevice,用 piper 的 audio_int16_bytes 直接 pipe 给 aplay(本教程采用此方案)。
Q3: TypeError: Unsupported data type: 'object' (sd.play 时报) voice.synthesize() 返回生成器,产出的是 AudioChunk 对象不是数组。正确取法: chunk.audio_int16_bytes 或 chunk.audio_int16_array 。
Q4: piper: command not found (但 python 里能 import piper) pip 用户级安装的 CLI 在 ~/.local/bin ,不在 PATH。 export PATH="$HOME/.local/bin:$PATH" 并写入 ~/.bashrc 。
注意:最终方案走 Python API,不依赖 CLI。
Q5: aplay 播出来变调 采样率错了。medium 模型输出 22050Hz, -r 参数必须与 .onnx.json 中的 sample_rate 一致。
Q6:播放/录音没声音
aplay -l / arecord -l 确认设备号,Clawbox 板载是 card 2
检查 ~/.asoundrc 默认卡设置
amixer -c 2 sget 'Speaker' / sget 'Capture' 查音量
排除硬件: speaker-test -D plughw:2,0 -t sine -f 440 -c 2
十一、后续可扩展方向
常驻化:llama-server + voice_assistant.py 用 systemd 开机自启 ,强烈建议的功能,不然每次都要调用非常麻烦!
唤醒词:openWakeWord 做免按键唤醒(4GB 内存需精打细算,建议 whisper 用 tiny,openWakeWord我找时间会试试看,想象一下: “”嘿贾维斯,帮我查一下什么是 clawbox~“, clawbox: “xxxxx 是一款。。。。。哈哈”)
更好的声音:Piper 中文音色有限,可试 sherpa-onnx 跑 GPT-SoVITS / CosyVoice / Kokoro82M(更吃算力,我个人猜测,你们有机会可以试试看~)
更大模型:换 16GB CM5 后可上 7B–8B, 记得clawbox拆了就不保修了哈。
GPU 加速:VideoCore VII 的 Vulkan 驱动尚不成熟,不推荐作为首选, 谁用谁知道,真是太晦涩难懂了。
教程整理时间:2026-09-28 | 设备:ED-CLAWBOX (CM5 4GB) | 全链路已实测跑通,如果你希望获取 DPF 文档,可以加群索取。
102
