7 Commits

Author SHA1 Message Date
244f28a0ab docs(rtc-only): 新增官方 Korvo-2 方案全面对比分析报告
基于 5 方对照(ES7210 datasheet + 电子吧唧原理图 + Korvo-2 V3.1.2 原理图 +
官方 pipeline.c + 当前 box_audio_codec.cc)输出 826 行分析报告:

- §一~五: 音频管线/RTC 编解码/任务线程/本地音频兼容性/抗抖动机制对比
- §六/补充·一~五: 麦克风收音根因分析 + 硬件 100% 等效证据 + GPIO 全对照 +
  ES7210 + AEC 完整启用方案(方案 D 2mic+1ref / 方案 E 1mic+1ref)
- §七~十: 实施路径/风险/执行建议
- §十一 决策记录: 基于 internal SRAM 仅剩 44KB 实测 + 服务端已有
  VAD/打断/AI 降噪 → 暂不实施方案 E,先走低风险高收益路径(服务端调优 +
  mic gain 27→33dB + Phase 7.5 网络优化)
- §11.9 交叉引用 Kapi_Rtc_toy 项目,指出 Kapi 资源更宽松更适合 AFE 实验
- §十二 版本历史 v1 → v2.0

关键结论:
- 你的板子 = 官方 Korvo-2 精简版(AEC 电路元件值 100% 相同, 音频 GPIO 100% 一致)
- 麦克风收音不准 95% 是网络/物理/服务端原因, 仅 5% 是缺设备端 AEC
- ESP-ADF 重构不推荐(工作量 3-4 周, 等同重写整个项目)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 14:37:05 +08:00
b8a5fe958f feat(rtc-only): Phase 6 - RTC 空闲软休眠(B+C 双源 + 真退房 + 字幕提示 + 内存兜底)
按 GSD 框架 .planning/milestones/digital_human_rtc/phases/phase_06_idle_hibernate/
规划完成 Phase 6 软退出 RTC 机制。替代旧的"40s 硬重启退出"方案。

## 核心变更

### 1. 倒计时刷新(B+C 双源方案)

| 方案 | 监听源 | 实施位置 | 状态 |
|------|--------|---------|------|
| A 扬声器流 | I2S/PCM 输出 | application.cc audio output 3 处 | **宏关闭**(PHASE6_ENABLE_AUDIO_FALLBACK) |
| **B 字幕监听** | RTC subtitle 消息 | application.cc:1300 subtitle 分支 | **启用** |
| **C 智能体状态** | RTC conv_status 消息 | application.cc:1260 conv_status 分支 | **启用** |

复用现有 DIALOG_IDLE_COUNTDOWN_SECONDS=40 不新增常量。

### 2. 真退出 RTC 房间(释放 License)

- 新增 Protocol 基类虚函数 LeaveRoom(默认回退到 CloseAudioChannel)
- VolcRtcProtocol::LeaveRoom 覆写:volc_rtc_stop + volc_rtc_destroy
  - 火山官方文档明确:真退房必须 leaveRoom + destroyRTCEngine
  - CloseAudioChannel 只 stop 不够(真人仍在房间继续计费)
- 服务端 AI 任务在 180s 内自动清理(火山平台机制)

### 3. EnterIdleHibernate / WakeFromHibernate

EnterIdleHibernate 流程(严格顺序):
1. protocol_->LeaveRoom()                  # 真退房
2. codec->EnableInput/Output(false)        # 重置 codec 状态机
3. recorder_pipeline_close()
4. hibernating_.store(true)                # 关键:先设标志阻止 PowerSaveTimer
5. esp_pm_configure(light_sleep=false)     # 双保险禁用 Light Sleep
6. SetDeviceState(kDeviceStateIdle)
7. idle_cycles_++ + NVS 持久化
8. 字幕"已自动退出RTC对话,按BOOT键重新连接RTC"(5 次重试间隔 200ms)

WakeFromHibernate 流程:
1. 检查 idle_cycles_ >= 50 → 硬重启清理碎片(兜底)
2. 清空字幕
3. ToggleChatState → OpenAudioChannel → 自动重建 rtc_handle_
4. RTC 重新加入房间(实测 2-3s 完成)

### 4. CanEnterSleepMode 加 hibernating 检查

防止 hibernate 期间 PowerSaveTimer 触发 esp_pm_configure(light_sleep=true)
导致 I2C 总线进入低功耗 → 唤醒后 ES7210/ES8311 通信失败 abort。

### 5. Dialog Watchdog 触发动作改造

旧:esp_restart() 整机重启(黑屏 15-25s + WiFi 重连)
新:Schedule(EnterIdleHibernate) 软退房(不熄屏 + 字幕提示)

### 6. BOOT 唤醒走 WakeFromHibernate 路径

iot_button 回调中检测 IsHibernating(),派发到独立 task 执行
WakeFromHibernate(避免阻塞 esp_timer 任务,CLAUDE.md 经验)。

### 7. OpenAudioChannel 适配重建

LeaveRoom 销毁 rtc_handle_ 后,OpenAudioChannel 头部检测 NULL
触发 Start() 异步重建,轮询 5s 等待就绪。NVS 缓存 device_secret
所以重建通常 100ms 完成。

## 实测验证(用户协作)

| 阶段 | 时间 |
|------|------|
| 40s 触发软休眠 |  |
| LeaveRoom 真退房 |  "✓ 已真退出 RTC 房间(leaveRoom + destroyRTCEngine)" |
| 屏幕保持 + 字幕显示 |  "已自动退出RTC对话,按BOOT键重新连接RTC" |
| BOOT 按键唤醒 |  |
| RTC 实例重建 |  100ms |
| RTC 重新加入房间 |  2-3s |
| 连续 2 次软休眠+唤醒 |  无 abort/I2C 失败 |
| 时间对比 | 旧硬重启 15-25s → 软休眠 3-5s(省 80%) |

## 6 个关键踩坑修复(详见 HIBERNATE_REPORT.md)

1. codec 状态机未重置 → 唤醒后 I2C abort
2. PowerSaveTimer Light Sleep 干扰 I2C 总线
3. hibernating_ 设置时序错误
4. dynamic_cast 在 -fno-rtti 下编译失败 → 改基类虚函数
5. LeaveRoom 后 OpenAudioChannel 直接失败 → 加重建逻辑
6. 字幕 LVGL 锁竞争 → 推迟到最后 + 5 次重试

## 文档产出(同时提交)

- .planning/.../phase_06_idle_hibernate/PLAN.md(含实施变更记录 V1-V6)
- .planning/.../phase_06_idle_hibernate/HIBERNATE_REPORT.md(验证报告)
- .planning/.../ROADMAP.md(Phase 1-5  + Phase 6 进行中状态更新)
- docs/Rtc_AIavatar/数字人表情渲染方案_云端预渲染+BLE+OTA.md
  新增第 19 章 RTC 空闲倒计时方案选型与软退出(9 小节)
- docs/Rtc_AIavatar/RTC软退出方案_移植参考.md
  完整移植参考(10 章 + 3 附录,可移植到其他火山 RTC 项目)
- docs/Rtc_AIavatar/音频卡顿_全局资源分析.md
  全局资源分析 + 13 项优化建议(不改代码)
2026-05-13 17:28:36 +08:00
eb96130fc9 feat(Rtc_AIavatar): 数字人透明 GIF 显示方案 PoC 完成(背景图+透明GIF叠加)
源代码变更:
- main/dzbj/bg_gif_demo.c/h: 方案 C 最终实现 - JPG 背景图(lv_img) + 透明 GIF(lv_gif) 叠加
- main/dzbj/dual_gif_demo.c/h: 方案 B 中间产物 - 双 GIF 循环切换
- main/dzbj/sprite_demo.c/h: 方案 A 已弃用 - DMA 直写 GRAM 与 LVGL 争抢 LCD IO 失败
- main/dzbj/ai_chat_ui.c: 集成 USE_BG_GIF_POC 开关,加载背景图+透明 GIF
- main/dzbj/lcd.c: panel_handle 移除 static,便于其他模块访问
- main/CMakeLists.txt: 新增 3 个 dzbj 模块编译

资源新增:
- spiffs_image/Background_360x360.jpg: 设备背景图(20KB)
- spiffs_image/hiyori_m05.gif: Cubism Editor 直接导出的透明 GIF(2.3MB)
- docs/Rtc_AIavatar/: Live2D 模型(Hiyori/Haru) + 32 段 Haru GIF + 方案文档第18章 PoC 实战记录
- tools/sprite_poc/: Python GIF→RGB565 转换脚本

踩坑要点(详见 docs/Rtc_AIavatar 第18章):
- PIL Image.quantize() 会破坏 RGBA 透明度,必须改用 gifsicle
- PIL 保存动画 GIF 仅第1帧有透明,后续帧不透明 - LVGL gifdec 按帧读取
- Cubism Editor 直接导出 GIF 才能逐帧保留透明信息(FREE 版限制部分模型)
- gifsicle --lossy 会严重锯齿化,去掉只保留 --colors 256 + -O3 即可
- 裁剪居中需用全帧 bbox 不能只看第1帧(Live2D 角色每帧位置有偏移)
- LVGL 默认不支持 PNG,背景图用 JPG + esp_jpeg 解码到 RGB565 buffer
- 透明 GIF 显示黑色背景: gifdec.c canvas 初始化 alpha 须改为 0x00
2026-05-12 17:14:49 +08:00
7868efed9b docs: 插件指南新增 GSD 执行框架章节 + GSD 项目参考文档
1、Claude Code 插件指南新增第九章:GSD 与工具链协作说明
   - 任务规模自动匹配(小事直接做/中事 gsd-quick/大事 gsd-plan)
   - GSD 与 hw-driver-workflow 的分层协作关系
   - GSD 常用命令速查表
   - 防上下文腐烂覆盖范围说明
2、插件指南恢复指南新增步骤 3.2(GSD 安装命令)
3、新增 docs/Get Shit Done项目.html(GSD 项目介绍参考文档)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 13:15:01 +08:00
99d7e910f1 补充提交:无关紧要的文件修改,不用理会 2026-03-27 10:59:33 +08:00
af58123d66 1、更新Claude插件高效运用的使用方法;
2、更新电子吧唧AI触屏版 → 按键版迁移总结
2026-03-23 10:30:44 +08:00
03496efecb 1、初始化代码,待适配中.... 2026-02-24 15:28:34 +08:00