248 lines
6.4 KiB
Markdown
248 lines
6.4 KiB
Markdown
# Day 18 - 性能优化与数据流匹配
|
||
|
||
**日期**: 2025-12-22
|
||
**主题**: 服务器性能优化、客户端与服务器数据流匹配、户外网络适配
|
||
|
||
---
|
||
|
||
## 今日概述
|
||
|
||
基于之前的诊断报告,对 AvaotaF1 客户端和 OpenAIglasses_for_Navigation 服务器进行了全面的性能优化,重点解决:
|
||
|
||
1. 画面卡顿/延迟问题
|
||
2. 盲道导航语音延迟
|
||
3. 客户端与服务器音频包大小不匹配
|
||
4. 户外手机热点网络适配
|
||
|
||
---
|
||
|
||
## 一、服务器性能优化
|
||
|
||
### 1.1 YOLO 推理优化
|
||
|
||
| 优化项 | 修改内容 | 文件 |
|
||
|--------|---------|------|
|
||
| **FP16 半精度** | 启用 `half=True` 加速推理 | `workflow_blindpath.py` |
|
||
| **动态输入分辨率** | 支持通过环境变量配置 `AIGLASS_YOLO_IMGSZ` | `workflow_blindpath.py` |
|
||
| **模型层融合** | 添加 `yolo_seg_model.fuse()` | `app_main.py` |
|
||
| **多次 CUDA 预热** | 启动时预热 3 次确保 kernel 编译 | `app_main.py` |
|
||
|
||
```python
|
||
# workflow_blindpath.py - 推理优化
|
||
imgsz = int(os.getenv("AIGLASS_YOLO_IMGSZ", "480"))
|
||
use_half = os.getenv("AIGLASS_YOLO_HALF", "1") == "1"
|
||
results = self.yolo_model.predict(image, imgsz=imgsz, half=use_half, ...)
|
||
```
|
||
|
||
### 1.2 障碍物检测优化
|
||
|
||
同样为 `obstacle_detector_client.py` 添加了 FP16 和可配置分辨率:
|
||
|
||
```python
|
||
imgsz = int(os.getenv("AIGLASS_OBS_IMGSZ", "480"))
|
||
use_half = os.getenv("AIGLASS_OBS_HALF", "1") == "1"
|
||
```
|
||
|
||
### 1.3 线程池增大
|
||
|
||
```python
|
||
# app_main.py
|
||
frame_processing_executor = ThreadPoolExecutor(max_workers=3) # 从2增加到3
|
||
```
|
||
|
||
### 1.4 检测间隔调整
|
||
|
||
| 参数 | 之前 | 之后 |
|
||
|------|------|------|
|
||
| 盲道检测间隔 | 8 帧 | 10 帧 |
|
||
| 障碍物检测间隔 | 15 帧 | 18 帧 |
|
||
| 全局播报冷却 | 1.2s | 0.8s |
|
||
|
||
---
|
||
|
||
## 二、语音延迟优化
|
||
|
||
### 2.1 客户端 TTS 预缓冲
|
||
|
||
```cpp
|
||
// main.cpp - 降低预缓冲
|
||
const size_t PRE_BUFFER_FRAMES = 8000; // 2秒 → 0.5秒
|
||
const size_t MIN_PLAY_FRAMES = 1600; // 0.3秒 → 0.1秒
|
||
```
|
||
|
||
### 2.2 服务器语音冷却
|
||
|
||
```python
|
||
# audio_player.py
|
||
_voice_cooldown = 1.5 # 从3秒降低到1.5秒
|
||
```
|
||
|
||
---
|
||
|
||
## 三、音频包大小统一
|
||
|
||
### 问题发现
|
||
|
||
| 端 | 之前 | 问题 |
|
||
|----|------|------|
|
||
| 客户端 | 30ms (480 samples, 960 bytes) | - |
|
||
| 服务器 | 期望 20ms (320 samples, 640 bytes) | ❌ 不匹配 |
|
||
|
||
### 修复方案
|
||
|
||
统一使用 **20ms** 音频包(更规范,符合 WebRTC/VoIP 标准):
|
||
|
||
**客户端修改**:
|
||
```cpp
|
||
// audio_capture.cpp
|
||
snd_pcm_uframes_t period_size = 320; // 480 → 320
|
||
|
||
// main.cpp
|
||
int16_t buffer[320]; // 480 → 320
|
||
snd_pcm_sframes_t frames_read = mic.read(buffer, 320);
|
||
```
|
||
|
||
**服务器修改**:
|
||
```python
|
||
# app_main.py
|
||
CHUNK_MS = 20 # 保持20ms
|
||
SILENCE_CHUNK = bytes(BYTES_CHUNK) # 重命名
|
||
```
|
||
|
||
---
|
||
|
||
## 四、户外网络适配
|
||
|
||
### 问题背景
|
||
|
||
室外使用 4G 手机热点,带宽波动大(1-5 Mbps),需要优化相机流配置。
|
||
|
||
### 配置方案对比
|
||
|
||
| 模式 | 帧率 | 质量 | 带宽 | 适用场景 |
|
||
|------|------|------|------|---------|
|
||
| 高性能 | 10fps | Q35 | ~400 KB/s | WiFi/5G |
|
||
| **户外稳定** ⭐ | 8fps | Q45 | ~200 KB/s | 4G 热点 |
|
||
| 极限省流 | 5fps | Q50 | ~100 KB/s | 弱网络 |
|
||
|
||
### 最终配置
|
||
|
||
```cpp
|
||
// camera.cpp - 户外稳定模式
|
||
#define DEFAULT_FPS 8 // 平衡流畅与带宽
|
||
#define DEFAULT_QUALITY 45 // 适度压缩节省带宽
|
||
```
|
||
|
||
---
|
||
|
||
## 五、.env 配置优化
|
||
|
||
为 RTX 3090 服务器创建了优化配置:
|
||
|
||
```bash
|
||
# GPU 配置
|
||
CUDA_VISIBLE_DEVICES=0
|
||
AIGLASS_DEVICE=cuda:0
|
||
|
||
# YOLO 推理
|
||
AIGLASS_YOLO_IMGSZ=640 # RTX 3090 用全分辨率
|
||
AIGLASS_YOLO_HALF=1 # 启用 FP16
|
||
AIGLASS_BLINDPATH_INTERVAL=6
|
||
|
||
# 障碍物检测
|
||
AIGLASS_OBS_IMGSZ=640
|
||
AIGLASS_OBS_INTERVAL=10
|
||
AIGLASS_OBS_HALF=1
|
||
|
||
# GPU 并发
|
||
AIGLASS_GPU_SLOTS=3
|
||
AIGLASS_AMP=bf16 # RTX 30 系列支持 BF16
|
||
```
|
||
|
||
---
|
||
|
||
## 六、代码清理
|
||
|
||
- 删除 `app_main.py` 中重复的 `import torch`(L17 和 L29)
|
||
|
||
---
|
||
|
||
## 七、修改文件汇总
|
||
|
||
### 客户端 (AvaotaF1)
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|---------|
|
||
| `main.cpp` | TTS 预缓冲降低、音频包 320 samples |
|
||
| `audio/audio_capture.cpp` | ALSA period_size 320 |
|
||
| `camera/camera.cpp` | 户外模式 8fps/Q45 |
|
||
|
||
### 服务器 (OpenAIglasses_for_Navigation)
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|---------|
|
||
| `app_main.py` | CHUNK_MS=20、删除重复import、模型融合预热 |
|
||
| `workflow_blindpath.py` | FP16、动态分辨率、间隔调整、冷却降低 |
|
||
| `obstacle_detector_client.py` | FP16、动态分辨率 |
|
||
| `audio_player.py` | 语音冷却 3s→1.5s |
|
||
| `.env` | RTX 3090 优化配置 |
|
||
| `.env.performance` | 性能调优模板 |
|
||
|
||
---
|
||
|
||
## 八、预期效果
|
||
|
||
### 在 RTX 3090 上
|
||
|
||
| 指标 | 优化前 (GTX 1060) | 优化后 (RTX 3090) |
|
||
|------|------------------|------------------|
|
||
| YOLO 推理 | ~100ms | ~15-25ms |
|
||
| 帧处理总时间 | ~150ms | ~40-60ms |
|
||
| 导航语音延迟 | ~3-4s | ~1-2s |
|
||
| 可支持帧率 | ~7 fps | ~20+ fps |
|
||
|
||
---
|
||
|
||
## 九、部署步骤
|
||
|
||
### 客户端(需重新编译)
|
||
|
||
```bash
|
||
cd AvaotaF1/avaota_app_demo/src
|
||
make clean && make
|
||
# 部署 avaota_client 到开发板
|
||
```
|
||
|
||
### 服务器端
|
||
|
||
```bash
|
||
cd OpenAIglasses_for_Navigation
|
||
source venv/bin/activate
|
||
python app_main.py
|
||
```
|
||
|
||
---
|
||
|
||
## 十、待验证
|
||
|
||
- [ ] RTX 3090 服务器实际推理速度
|
||
- [ ] 户外 4G 热点网络稳定性
|
||
- [ ] 盲道导航语音播报是否正常
|
||
- [ ] 音频 20ms 包大小对 ASR 识别率的影响
|
||
|
||
---
|
||
|
||
## 十一、深夜紧急修复 (Late Night Hotfixes)
|
||
|
||
### 11.1 传输瓶颈优化
|
||
- **问题**:多客户端(浏览器+Recorder)连接时,WebSocket 串行发送导致服务器卡顿。
|
||
- **修复**:在 `app_main.py` 中引入 `asyncio.gather` 实现并行广播,消除阻塞。
|
||
|
||
### 11.2 运行时崩溃修复
|
||
- **问题**:`app_main.py` 缺少部分常量 (`MODEL`) 和导入 (`register_stream_route`, `broadcast_pcm16_realtime`)。
|
||
- **修复**:补全了缺失的代码,解决启动和运行时的 `NameError`。
|
||
|
||
### 11.3 GPU 配置加载修复
|
||
- **问题**:虽然创建了 `.env`,但 `app_main.py` 代码中未调用 `load_dotenv()`,导致配置未生效(模型仍跑在 CPU)。
|
||
- **修复**:添加 `load_dotenv()` 调用,确保 `CUDA_VISIBLE_DEVICES` 生效,彻底解决画面假死问题。
|