179 lines
6.1 KiB
Markdown
179 lines
6.1 KiB
Markdown
# Day 22 - GLM API 修复 + SenseVoice 语言修复
|
||
|
||
**日期**: 2025-12-26
|
||
**主题**: AI 对话链路修复
|
||
|
||
---
|
||
|
||
## 🔧 GLM API 升级 (10:00)
|
||
|
||
**问题**:Day 21 的 GLM API 调用失败 (Error 400/1210)
|
||
**原因**:使用了错误的 SDK 和模型名称
|
||
**修复**:升级到官方 `zai-sdk` + `glm-4.5-flash`
|
||
|
||
### 修改对比
|
||
|
||
| 项目 | 修改前 | 修改后 |
|
||
|------|--------|--------|
|
||
| SDK | `openai` | `zai-sdk` |
|
||
| 模型 | `glm-4-flash` | `glm-4.5-flash` |
|
||
| 客户端 | `OpenAI(...)` | `ZhipuAiClient(...)` |
|
||
|
||
### 代码变更 (`glm_client.py`)
|
||
```python
|
||
# 修改前
|
||
from openai import OpenAI
|
||
MODEL = "glm-4-flash"
|
||
_client = OpenAI(api_key=API_KEY, base_url=API_BASE)
|
||
|
||
# 修改后
|
||
from zai import ZhipuAiClient
|
||
MODEL = "glm-4.5-flash"
|
||
_client = ZhipuAiClient(api_key=API_KEY)
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 SenseVoice 语言修复 (10:08)
|
||
|
||
**问题**:Day 21 识别出韩语字符 (`그`)
|
||
**原因**:`language="auto"` 自动检测错误
|
||
**修复**:固定为 `language="zh"` 中文
|
||
|
||
### 代码变更 (`sensevoice_asr.py`)
|
||
```python
|
||
# 修改前
|
||
language="auto"
|
||
|
||
# 修改后
|
||
language="zh" # 固定为中文,避免 auto 误判
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 扬声器杂声修复 (10:48)
|
||
|
||
**问题**:无 TTS 播放时扬声器有杂声
|
||
**原因**:`loopback debug` 开关将麦克风信号回环到 I2S 输出
|
||
**修复**:在 `audio_player.cpp` 中禁用 loopback 开关
|
||
|
||
### 代码变更 (`audio_player.cpp`)
|
||
```cpp
|
||
// 在 setup_mixer() 中
|
||
if (switch_name.find("loopback") != std::string::npos) {
|
||
snd_mixer_selem_set_playback_switch_all(elem, 0); // 禁用
|
||
LOG_INFO("DISABLED playback switch for '%s' (noise reduction)", name);
|
||
}
|
||
```
|
||
|
||
### 注意事项
|
||
- **不能禁用 MIC playback switch**:Day 12 发现禁用会导致麦克风无数据(硬件限制)
|
||
- 如果此修复不彻底,可能需要硬件层面改进(加磁环、屏蔽线)
|
||
|
||
---
|
||
|
||
## 📁 修改文件汇总
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|----------|
|
||
| `glm_client.py` | 升级到 zai-sdk + glm-4.5-flash |
|
||
| `sensevoice_asr.py` | 语言设置从 auto 改为 zh |
|
||
| `test_glm.py` | **新增** GLM API 测试脚本 |
|
||
|
||
---
|
||
|
||
## 🧪 验证说明
|
||
|
||
### 服务器测试步骤
|
||
```bash
|
||
cd ~/ProgramFiles/OpenAIglasses_for_Navigation
|
||
|
||
# 1. 同步代码(从本地推送或 git pull)
|
||
|
||
# 2. 启动服务器(主程序已集成修复)
|
||
python app_main.py
|
||
```
|
||
|
||
### 验证点
|
||
- [ ] 语音识别结果为中文(不再出现韩语字符)
|
||
- [ ] AI 回答与问题相关 (GLM-4.6v-flash)
|
||
- [ ] VAD 响应灵敏,无首字丢失
|
||
- [ ] 导航语音播报正常 (Chipmunk effect 确认为正常现象)
|
||
|
||
|
||
|
||
|
||
---
|
||
|
||
## 🔧 VAD 语音截断修复 (14:30)
|
||
|
||
**问题**:语音指令首字经常丢失(如"开始导航"识别为"导航")
|
||
**原因**:VAD 触发后才开始录制,错过了触发前的几百毫秒关键音节
|
||
**修复**:在 `server_vad.py` 中引入 `pre_speech_buffer` 环形缓冲区 (300ms)
|
||
**效果**:检测到语音时,自动回溯并拼接前 300ms 音频,首字识别率显著提升
|
||
|
||
### 代码原理
|
||
```python
|
||
# 环形缓冲队列
|
||
self.pre_speech_buffer = collections.deque(maxlen=PRE_SPEECH_CHUNKS)
|
||
# 触发时拼接
|
||
packet = b''.join(list(self.pre_speech_buffer)) + chunk
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 TTS 语速与音频底噪 (15:50)
|
||
|
||
### 1. 导航语音语速过快 ("Chipmunk Effect")
|
||
**现象**:导航提示音(如"远处发现斑马线")语速极快,音调偏高
|
||
**调查**:
|
||
- 检查采样率:确认 Client/Server 均为 16kHz,配置无误
|
||
- 检查源文件:发现 `远处发现斑马线.WAV` 实际时长仅 **1.02s**,而 `map.zh-CN.json` 预期 **1.6s**
|
||
**结论**:源文件录制语速本身较快
|
||
**决策**:用户确认偏好此语速,**取消修复**(保持原样)
|
||
|
||
### 2. 音频回环底噪
|
||
**现象**:扬声器有持续静电底噪
|
||
**分析**:
|
||
- 此前怀疑硬件接地问题(手触开发板底噪消失)。
|
||
- **最终确认**:连接电脑 USB/串口导致的**共地干扰** (PC 机箱未接地,或 USB 供电干扰)。
|
||
**解决方案**:
|
||
- **移除串口,使用电池独立供电** -> **杂音完全消失**。
|
||
- 软件上仍保持 `ADC Playback Volume` 80% 以防万一,但核心问题已由电源隔离解决。
|
||
|
||
|
||
---
|
||
|
||
## 🛑 踩坑与反思 (Lessons Learned)
|
||
|
||
今天开发过程中经历了几个关键的“弯路”,值得记录以避免重蹈覆辙:
|
||
|
||
### 1. 音频问题的归因偏误
|
||
- **弯路**:听到 TTS 语速快 ("Chipmunk Effect"),第一反应是**代码逻辑错误**(认为采样率 8k/16k 不匹配),花费大量时间排查 `audio_compressor` 和 `audio_player`。
|
||
- **真相**:实际上是**源文件本身**录制语速就这么快(1.0s vs 预期 1.6s)。
|
||
- **教训**:遇到音频异常,**优先检查源文件 (Source Asset)** 的属性,不要预设是代码 BUG。
|
||
|
||
### 2. 硬件 Mixer 的隐形耦合
|
||
- **弯路**:为了消除回环噪音,直接在代码中将 `ADC Playback Volume` 设为 0(静音)。
|
||
- **后果**:导致麦克风采集数据全为 0,一度以为驱动损坏。
|
||
- **真相**:该开发板 (V821) 的 Codec 硬件通路上,**ADC Playback Volume 同时控制采集增益**。
|
||
- **教训**:嵌入式音频开发中,Mixer 控件往往存在硬件级耦合,调整前需小步验证,不能想当然地“全关”。
|
||
|
||
### 3. VAD 的时序陷阱
|
||
- **弯路**:语音首字识别丢失,一直在调整 VAD 的**灵敏度阈值 (threshold)**。
|
||
- **真相**:阈值再低也需要时间触发,触发时说话人已经发出了第一个音节。
|
||
- **教训**:实时语音交互中,**环形缓冲区 (Lookback Buffer)** 是必须的,它能“挽回”触发前的那几百毫秒关键信息。
|
||
|
||
---
|
||
|
||
## 📝 Day 22 总结
|
||
|
||
| 类别 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| GLM API 升级 | ✅ | zai-sdk + glm-4.6v-flash |
|
||
| SenseVoice 语言修复 | ✅ | language="zh" |
|
||
| VAD 截断修复 | ✅ | Ring Buffer (300ms) |
|
||
| TTS 语速排查 | ✅ | 确认源文件特性,用户决定保留 |
|
||
| 音频底噪优化 | ⚠️ | 软件80%音量,硬件需接地 |
|
||
| 待服务器验证 | ⏳ | 需要部署并测试 |
|