Files
Docs/DevLogs/Day22.md
2025-12-31 16:18:28 +08:00

179 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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%音量,硬件需接地 |
| 待服务器验证 | ⏳ | 需要部署并测试 |