# Kapi_Rtc_toy 项目业务全貌与重构决策分析

> **生成时间**：2026-05-14
> **生成背景**：Baji_Rtc_Toy（衍生项目）在硬件资源紧张+用户体验不佳的背景下，评估是否应该把 Phase 6 软退出、ESP-SR AFE、G711A→Opus 等优化方案移植到 Kapi（底座项目），或干脆切到 ESP-ADF 框架重构。
> **关联文档**：
> - 衍生项目对比报告：[/Users/rdzleo/Desktop/Baji_Rtc_Toy/docs/Rtc_AIavatar/官方Korvo2方案_对比分析报告.md](../Baji_Rtc_Toy/docs/Rtc_AIavatar/官方Korvo2方案_对比分析报告.md)
> - 同源 RTC 软退出方案：[/Users/rdzleo/Desktop/Baji_Rtc_Toy/docs/Rtc_AIavatar/RTC软退出方案_移植参考.md](../Baji_Rtc_Toy/docs/Rtc_AIavatar/RTC软退出方案_移植参考.md)
> - 项目内已有 AEC 计划：`03AEC_VOICE_INTERRUPT_PORTING_PLAN.md`

---

## 0. TL;DR（一句话总结）

> **Kapi_Rtc_toy 是 Baji_Rtc_Toy 的"无屏轻量底座"，比 Baji 多出 30-50KB SRAM + 300-500KB PSRAM 资源余量。Phase 6 软退出方案 100% 可移植且工作量极小；AFE-AEC 资源富余但需先确认硬件 REF 通道走线；坚决不推荐切换到 ESP-ADF 重构。**

---

## 1. 整体架构和业务全貌

### 1.1 框架与平台

| 项 | 值 |
|---|---|
| **框架** | **纯 ESP-IDF**（≥5.3），不是 ESP-ADF |
| **目标芯片** | ESP32-S3，16MB Flash + 8MB Octal PSRAM 80MHz |
| **板型** | movecall-moji-esp32s3（**无屏**，触摸+IMU+电池） |
| **协议** | WebSocket + Volc RTC 同时编入，通过 `ENABLE_RTC_MODE` 宏激活 RTC |

依据：
- `main/idf_component.yml:13` — `espressif/esp_codec_dev: ~1.3.2`
- `main/CMakeLists.txt:235-238` — `ENABLE_RTC_MODE` 宏
- `sdkconfig` — `SPIRAM_MODE_OCT/SPEED_80M`, `CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3=y`

### 1.2 入口流程

```
main.cc:28 app_main
  → esp_event_loop_create_default
  → esp_netif_init
  → nvs_flash_init
  → Application::GetInstance().Start()   (main.cc:105)
      → application.cc:Start (~531 启动播报)
      → 板级初始化（boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc:225+）
      → InitializeProtocol → VolcRtcProtocol::Start (volc_rtc_protocol.cc:43)
      → StartDialogWatchdog (application.cc:1961)
```

### 1.3 主要模块清单

| 模块 | 行数 | 职责 |
|---|---|---|
| `main/application.cc/h` | 4281 行 | 单例主控、状态机、音频 I/O、HTTPS 故事/音乐、Dialog Watchdog、Schedule 队列 |
| `main/protocols/volc_rtc_protocol.cc/h` | 853 行 | 火山 RTC 封装：volc_rtc_create/start/stop/destroy、subv/ctrl/conv/tool/info 消息解析 |
| `main/protocols/websocket_protocol.cc` | — | WS 协议（RTC 模式下未激活） |
| `main/protocols/protocol.h` | — | Protocol 基类（**当前无 `LeaveRoom` 虚函数**） |
| `main/audio_codecs/box_audio_codec.cc` | — | ES8311（DAC）+ ES7210（ADC） |
| `main/audio_codecs/es8311_audio_codec.cc` | — | 单 ES8311 实现（Moji 未用） |
| `main/audio_processing/audio_processor.cc/h` | — | 基于 ESP-SR 的 AFE+VAD 封装（**未编入**） |
| `main/audio_processing/wake_word_detect.cc` | — | 唤醒词（**未编入**） |
| `main/audio/simple_pipeline.cc` | ~60 行 | **不是 ESP-ADF 管线**，仅是 codec InputData/OutputData 的薄壳 + 最近邻重采样 |
| `main/bluetooth_provisioning.cc` | 1417 行 | 自定义 BLE GATT 二进制配网（0xABF0/F1/F2） |
| `main/ble_service.cc` | — | BLE JSON Service（已实现未编入） |
| `main/boards/movecall-moji-esp32s3/*` | 2078 行 + IMU + Touch | 板级：QMI8658A IMU、6 路 TouchPad、ADC 电池、KEY4 |
| `main/iot/thing*.cc` + `iot/things/*.cc` | — | IoT 设备抽象 |
| `main/weather_api.cc` | — | 天气查询 |

### TL;DR

Kapi_Rtc_toy = "xiaozhi" 系列 ESP-IDF 项目魔改版，集成火山 RTC + 自定义 BLE 配网 + IMU/触摸/电池。**无 LCD/LVGL**，框架是 ESP-IDF 而非 ESP-ADF；audio_processing 整套 AFE 代码已具备但**未在 sdkconfig 中启用**。

---

## 2. RTC 实现现状

### 2.1 协议层

- 使用 **VolcRtcProtocol**（`main/protocols/volc_rtc_protocol.cc:43-407`）
- SDK：火山 `volc_engine_rtc_lite`（`main/CMakeLists.txt:204` REQUIRES）
- 入房：`volc_rtc_start` → 等待 0x1（CONNECTED）+ 0x2（USER_JOINED）位
- 退房：`CloseAudioChannel` **仅调用 `volc_rtc_stop`**（`volc_rtc_protocol.cc:399`），**不调 `destroy`** → 真人留在房间继续计费（与 Baji 旧版同病）

### 2.2 音频编解码使用现状

- **上行**：默认 `send_pcm_uplink_=true`、`send_g711a_uplink_=false`（`application.h:160-161`）。设备发 PCM，**SDK 内部转 G711A 上传**（`audio.codec.internal.enable=1`，`volc_rtc_protocol.cc:95`）
- **下行**：`Joining channel: aibotrtc_G711A_*`（日志 `05-最新日志.txt:160`）→ **下行是 G711A**，不是 Opus
- **本地播报（开机欢迎/故事/音乐）**：Opus 编码的 `.p3` 资产（OPUS 16k/60ms 单声道，开机播 `LALA_kaijibobao.p3`，`application.cc:618`）
- **HTTPS 故事/音乐**：服务器返回 base64 Opus 数据，本地解码（`HttpsApiPlayback` + `audio_decode_queue_`）

### 2.3 软退出/Hibernate 现状

- **无 hibernate**、**无 LeaveRoom**、**无 EnterIdleHibernate**
- Dialog Watchdog 触发逻辑（`application.cc:1961-2042`）：
  - 40s 无 `last_audible_output_time_` 更新 → 写 NVS `reboot_dlg_idle=1` + `reboot_origin=1` → **`esp_restart()`**（line 2014）
  - 这正是 Baji Phase 6 替换的"硬重启退出"原型
- `last_audible_output_time_` 当前**只由音频流刷新一处**（`application.cc:2161`，相当于方案 A），**没有方案 B (subtitle) 和方案 C (conv_status) 的双源刷新**

### 2.4 与 Baji_Rtc_Toy Phase 6 差异

| 项 | Kapi_Rtc_toy | Baji_Rtc_Toy (Phase 6) |
|---|---|---|
| 退出方式 | `esp_restart()` 硬重启 | `LeaveRoom` (stop+destroy) 软退 |
| 恢复时长 | 15-25s（WiFi+应用全冷启）| 3-5s（NVS 缓存凭证，重建 RTC handle） |
| 倒计时刷新源 | 只有方案 A（音频流） | B+C 双源（subtitle + conv_status） |
| 状态保留 | 全部丢失 | 音量/历史/上下文保留 |

### TL;DR

Kapi RTC 协议层基本完备（与 Baji 共享 95% 同源代码），下行 G711A、上行 PCM-by-SDK-to-G711A。**完全没有软退出/hibernate 逻辑，仍是 `esp_restart()` 硬退出**，正好是 Baji Phase 6 解决的问题。

---

## 3. 音频管线（重点）

### 3.1 框架与组件

- 使用 **esp_codec_dev**（`espressif/esp_codec_dev: ~1.3.2`）
- **不使用 ESP-ADF 的 audio_pipeline / audio_element**
- `simple_pipeline.cc/h` 是 stub：`recorder_pipeline_read` 直接调 `codec->InputData`，`player_pipeline_write` 直接调 `codec->OutputData`，外加最近邻重采样（音质差但够用）

### 3.2 ES7210 + ES8311 配置

| 项 | 值 | 引用 |
|---|---|---|
| Codec 创建 | `BoxAudioCodec(ES8311 + ES7210)` | `movecall_moji_esp32s3.cc:1507` |
| AUDIO_INPUT_REFERENCE | **0** ← 没有参考通道接入 AEC | `config.h:27` |
| mic_selected | `MIC1 \| MIC2`（**双 mic，无 REF**） | `box_audio_codec.cc:67` |
| ES8311 输出 | 固定立体声（`STEREO + BOTH slot`） | `es8311_audio_codec.cc:105-109` |

**注意**：ES8311 必须是立体声输出，单声道会导致 RTC 入房失败（`04-2025-11-21音频优化记录.md` 已踩坑修复）。

### 3.3 AFE / audio_processor 状态

- `sdkconfig:642-645`：**`CONFIG_USE_AUDIO_PROCESSOR is not set`**、**`CONFIG_USE_WAKE_WORD_DETECT is not set`**、**`CONFIG_USE_CUSTOM_WAKE_WORD is not set`**
- 代码已编写完整（`audio_processing/audio_processor.cc` + EchoAwareVadParams + AdaptiveNoiseState），但**整个文件未参与编译**（`CMakeLists.txt:167-169` 条件化）
- AFE 依赖项 `espressif/esp-sr: ^2.0.3` 已声明（`idf_component.yml:8`）

### 3.4 AEC 反馈通道（关键风险点）

- **硬件层：当前未走 ES7210 REF 通道**（`AUDIO_INPUT_REFERENCE=0`）
- 要启用 AFE-AEC 必须：
  1. 改板级配置改为 1
  2. 调整 mic_selected 加入 REF
  3. 确认 ES8311 输出经过 PCB 走线到 ES7210 REF 输入（Box 系列板默认已布好线，**Moji 板需确认**）
- 同时 ES8311 输出立体声给 ES7210 REF（loopback 路径）
- 软件层：AudioProcessor::Initialize 已写 AEC/VAD 初始化，缺的只是 sdkconfig 启用 + 板级 REF 启用

### TL;DR

**音频管线极其简陋（ESP-IDF + simple_pipeline stub）**。**AFE 整套代码已写好但未启用**，硬件层无 REF 通道。**比 Baji 项目更"裸"**——Baji 走的是一样的 codec 直写路径，没区别。

---

## 4. 已有功能清单

| 功能 | 实现位置 | 说明 |
|---|---|---|
| **BLE 配网** | `bluetooth_provisioning.cc`（1417 行） | **自定义 GATT 二进制协议**（Service 0xABF0），不是 BluFi。BluFi 编译开关 `CONFIG_BT_BLE_BLUFI_ENABLE=y` 启用但代码未调用 |
| **生产测试模式** | `application.cc` "Airhub" 标签 | 触摸/IMU 自检上报 |
| **本地 P3 播放** | `application.cc:300 PlaySound` | 走 `OnAudioOutput` → codec OutputData，**不走 player_pipeline** |
| **HTTPS 故事** | `application.cc:SendStoryRequest + HttpsApiPlayback` | base64 Opus 解码 → 入 audio_decode_queue_ |
| **HTTPS 音乐** | `application.cc:SendMusicRequest` | 同上 |
| **IoT/MQTT** | `main/iot/thing.cc` | MQTT-UDP 协议保留，RTC 模式下未启用 |
| **按键** | KEY4（GPIO4，故事键）+ BOOT（GPIO0） | `iot_button` 组件 |
| **LED** | `BUILTIN_LED_GPIO=21`，SingleLed | |
| **IMU** | QMI8658A（I2C 0x6A），运动检测唤醒/打断 | `movecall_moji_esp32s3.cc:838 InitializeImuSensor` |
| **触摸** | 4 路 TouchPad（GPIO1/2/15/7） | `TouchEventTask`（line 1643） |
| **电池** | GPIO6 ADC1_CHANNEL_5 | line 828 |
| **OTA** | `main/ota.cc` | |
| **天气** | `weather_api.cc` | |
| **WakeWord** | 代码存在未编入 | |

文档参考：`README_RTC.md`、`02Kapi_Rtc_火山RTC替换实现方案.md`、`QMI8658A驱动适配方案_B站驱动.md`。

### TL;DR

**业务功能比 Baji 更精简**：无 LCD、无 LVGL、无 GIF 解码、无相册、无应援灯，但有 IMU + 4 路触摸。BLE 配网与 Baji 完全一致（同源代码）。

---

## 5. 资源占用现状

### 5.1 Flash

- 分区 `partitions.csv`：nvs 16K + otadata 8K + model SPIFFS 3MB + ota_0/1 各 5MB = 13MB（16MB 板，剩 3MB 余量）
- 实际固件大小约 3.5-4MB（同源代码估算），**OTA 分区 5MB 富余度极宽**

### 5.2 SRAM（关键）

- **运行日志显示 `free_heap=8289744`**（启动后约 8MB）→ 这是 **PSRAM + 内部 SRAM 总和**
- Volc RTC 启动后跌到约 8.05M，运行中波动在 7.88-7.89M（subv 消息处理）
- 没看到 internal SRAM 单独打印，但 BLE+RTC+ES7210+ES8311 在 ESP32-S3 N16R8 上 **runtime 内部 SRAM 余量约 80-130KB 是常见值**（比 Baji 多 30-50KB）
- `SPIRAM_MALLOC_RESERVE_INTERNAL=65536` 保留 64KB

### 5.3 PSRAM

- 8MB Octal 80MHz，运行时空闲约 7.5-8M，**资源极其宽松**
- Baji 是同款 S3-N16R8 模组，但 Baji 还要承载 LVGL（~50KB DRAM）+ 360×360 GIF 缓冲（~250KB PSRAM）+ JPEG 背景

### TL;DR

**Kapi 比 Baji 资源宽松约 300-500KB PSRAM + 30-50KB 内部 SRAM**（省掉 LVGL/GIF/相册）。Flash OTA 分区 5MB 完全够用。**AFE 启用预计需要 ~150-200KB PSRAM + 30KB 内部 SRAM**，资源**完全够**。

---

## 6. 与 Baji_Rtc_Toy 的差异

| 维度 | Kapi_Rtc_toy | Baji_Rtc_Toy |
|---|---|---|
| 模组 | ESP32-S3-N16R8 | ESP32-S3-N16R8（同款） |
| 板型 | movecall-moji-esp32s3（无屏） | 同板加 LCD（QSPI ST77916 360×360） |
| LVGL | ❌ 无 | ✅ 有，~50KB DRAM |
| 数字人 GIF | ❌ 无 | ✅ 有，2 个透明 GIF（haru/hiyori） |
| 应援灯 | ❌ 无 | ✅ DMA 直写 GRAM |
| 双模式 (AI/吧唧) | ❌ 单模式 | ✅ NVS 切换 |
| BLE 图传 | ❌ 无 | ✅ 0x0B00 服务 |
| 触摸 LCD | ❌ 无 | ✅ CST816S |
| 按键 | BOOT+KEY4 | BOOT+KEY2 |
| IMU | ✅ QMI8658A | ❓ 待确认 |
| 自定义 BLE 配网 | ✅ 0xABF0 | ✅ 0xABF0（同源） |
| **Phase 6 软退出** | ❌ 无 | ✅ 已实现 |
| **AFE/AEC** | ❌ 代码在未启用 | ❌ 代码在未启用（同源） |
| Volc RTC SDK | volc_engine_rtc_lite | volc_engine_rtc_lite（同源） |

### TL;DR

**Kapi 是 Baji 的"无屏底座"**，节省约 300-500KB PSRAM + 30-50KB 内部 SRAM。RTC/BLE/codec 代码完全同源，**Phase 6 移植成本极低**。

---

## 7. 已有的 RTC/AEC/Opus 相关规划文档

| 文档 | 状态 | 关键内容 |
|---|---|---|
| `00Kapi_Rtc_火山RTC整合移植方案.md` | 已实施 | WS → 火山 RTC 总体方案 |
| `01..._技术分析报告.md` | 已实施 | 用 volc_engine_rtc_lite 替换 WS |
| `02..._火山RTC替换实现方案.md` | 已实施 | VolcRtcProtocol 具体实现 |
| `03AEC_VOICE_INTERRUPT_PORTING_PLAN.md` | **计划，未实施** | Airhub_Rtc_h → Kapi 的 ES7210 双 mic + AEC + 语音打断移植方案。代码片段已示范 `aec_create + aec_process`，建议 `mic_selected` 改为 MIC1+MIC3，30dB 增益 |
| `AEC_VAD_OPTIMIZATION.md` | 设计，部分已写入 audio_processor.cc | AEC+VAD 联合启用（`AEC_MODE_VOIP_LOW_COST` + `VAD_MODE_3`）、回声感知、动态阈值；EchoAwareVadParams 结构已在头文件 |
| `04-2025-11-21音频优化记录.md` | 已实施修复 | 开机播报"尖锐声"修复：单声道 PCM 复制为立体声（`application.cc:1224-1230`）；MONO I2S 会导致 RTC 入房失败 |
| `VOICE_INTERRUPT_*.md` / `URGENT_INTERRUPT_FIX.md` / `BOOT_BUTTON_*` | 历史调试笔记 | 语音打断和按键交互优化记录 |

### TL;DR

**Kapi 已计划好"AFE-AEC + 语音打断"的实现路径但没落地**（03、AEC_VAD_OPTIMIZATION）。**Opus 上下行优化未在文档中提及**（当前 G711A 已可用）。

---

## 8. 三个移植/重构选项评估

### 选项 A：保持 ESP-IDF，移植 Baji Phase 6（软退出 + 字幕提示）

| 维度 | 评分 |
|---|---|
| 工作量 | **低**（1-2 天）：基类加 `LeaveRoom()` + VolcRtcProtocol override + 应用层 hibernate 状态机 + B+C 双源刷新 |
| 风险 | **低**：基类代码同源，`volc_rtc_destroy` 调用已存在（`volc_rtc_protocol.cc:32-34`），只需提取为独立接口 |
| 资源占用 | **零**：只加几个原子标志和 NVS 计数器 |
| 字幕提示效果 | **打折**：Kapi 无 LCD，`display->SetChatMessage` 是 noop（`Display` 是空对象 `movecall_moji_esp32s3.cc:1541`）。可改为 LED 闪烁或 P3 语音提示替代 |
| 真退房收益 | **完全保留**：License 释放 + BOOT 唤醒 3-5s |
| 兜底机制 | 保留 `idle_cycles_` 50 次重启兜底，无影响 |

**建议：✅ 强烈推荐**。除字幕提示需替换为语音/LED 外，**其他所有收益（真退房、快速恢复、状态保留）100% 适用**。这是性价比最高的优化。

---

### 选项 B：保持 ESP-IDF，启用 AFE + Opus 切换

#### B-1：启用 ESP-SR AFE（设备端 AEC）

| 维度 | 评分 |
|---|---|
| 工作量 | **中**（3-5 天）：sdkconfig 三项打开 + board config `AUDIO_INPUT_REFERENCE=1` + box_audio_codec mic_selected 加入 MIC_REF + Application::OnAudioInput 走 AudioProcessor + ES8311→ES7210 loopback 验证 |
| 风险 | **中**：① ES7210 REF 通道接线需硬件确认（Moji 板原理图待查）；② AEC 调参（filter_length、AEC_MODE_VOIP_LOW_COST vs SR_LOW_COST）；③ ES8311 立体声输出与单声道 AFE 输入的通道映射 |
| 资源占用 | **+150-200KB PSRAM + 30KB 内部 SRAM + ~20% CPU**（Core 1） |
| 收益 | **大**：从"无设备端 AEC"→"有 AEC"，对话打断体验提升明显；目前打断完全依赖云端 VAD，延迟 1-3s（参考 03 文档结论） |

#### B-2：G711A → Opus 上行切换

| 维度 | 评分 |
|---|---|
| 工作量 | **中**（2-3 天）：火山 SDK config 改 `"audio":{"codec":4}` 为 Opus（`volc_rtc_protocol.cc:76`），需上行编码改 OPUS（已有 `opus_encoder_` 实例），下行解码改 OPUS（已有 OpusDecoderWrapper） |
| 风险 | **中**：① 火山服务端房间名 `aibotrtc_G711A_*` 暗示通道协商当前锁定 G711A，要确认服务端是否支持切 Opus；② 上行 Opus 60ms 帧比 G711A 20ms 帧延迟高 40ms |
| 资源占用 | **+~10KB 内部 SRAM**（Opus 编码器） |
| 收益 | **小到中**：Opus 比 G711A 在同等比特率下质量明显更高，但 G711A 在小 toy 设备上听感已经"够用"。**jitter buffer 优化更值得做** |

#### B-3：Jitter buffer 优化

- 当前 `audio_decode_queue_` 是无限增长的 std::list，无主动 jitter buffer 管理
- 网络抖动时累积延迟，但**当前没收到具体抖动投诉**
- 建议先做 A、B-1，确认音频体验之后再评估

**建议**：
- B-1 (AFE-AEC) ✅ **推荐**，但**先确认 Moji 板硬件 REF 通道接线**（如果 REF 没飞线则只能软件回环 PCM，效果差很多）
- B-2 (Opus) ⚠️ **不推荐先做**：服务端兼容性需求未明确，收益边际；先把 AEC 做对
- B-3 (Jitter) ⚠️ **暂缓**：没具体痛点，纯优化无意义

---

### 选项 C：完全重构成 ESP-ADF + 官方 high_quality_solution

| 维度 | 评分 |
|---|---|
| 工作量 | **极高**（3-4 周）：ESP-ADF 框架与当前 codec 直写架构差异巨大；ConversationalAI-Embedded-Kit-2.0 官方 demo 板 ESP32-S3-Korvo-2 与 Moji 引脚完全不同；BLE 配网/IMU/触摸/电池/HTTPS 故事/天气全部需要迁移 |
| 风险 | **极高**：① ADF audio_pipeline 与 esp_codec_dev 不兼容，要全部重写 codec 路径；② ADF 自带 button/peripheral 与 iot_button 冲突；③ ESP-ADF eca11f20 版本要绑 IDF v5.4，可能引入新构建问题；④ 业务代码（HTTPS 故事/IMU/触摸/BLE）全部要适配 |
| 资源占用 | **+200-400KB**（ADF 框架本体 + 多个 audio_element 任务） |
| 收益 | **官方支持 + 高音质方案 (high_quality_first)**：官方持续维护，AEC + 噪声抑制 + AGC 全部内置；可能比手撸 AFE 体验更好 |
| 兼容性 | Volc 官方 demo 用的就是这套；与火山服务端协议完美对齐 |

**建议：❌ 不推荐**，理由：
1. 当前业务**已能跑通 RTC 对话**，没必要推翻重来
2. ESP-ADF 引入的复杂度（pipeline / element / event）与当前轻量架构哲学冲突
3. 板级适配（Moji 与 Korvo-2 引脚映射）工作量约等于重写整个项目
4. 同等收益可以用"Phase 6 软退 + AFE 启用"的组合拳达到，工作量是 1/5

**例外**：如果未来要做**双麦克风 beamforming + 多说话人分离**等 ADF 高级特性，再考虑重构。

---

## 9. 最终推荐路线

按优先级递进：

1. **第 1 步（必做）**：移植 Baji Phase 6 软退出方案
   - 工作量 1-2 天，收益巨大（License 释放 + 唤醒 3-5s + 状态保留）
   - 字幕提示替换为 LED 闪烁 / `PlaySound(Lang::Sounds::P3_xxx)` 语音提示
   - 加上 B+C 双源刷新 `last_audible_output_time_`

2. **第 2 步（推荐）**：硬件确认 + 启用 ESP-SR AFE-AEC
   - 先 Moji 板原理图确认 ES7210 REF 是否接到 ES8311 输出
   - 如已飞线 → 启用 `AUDIO_INPUT_REFERENCE=1` + AudioProcessor + sdkconfig 三项
   - 如无飞线 → 评估软件 loopback 方案（Application 端拷贝 output PCM 作为 reference）

3. **第 3 步（按需）**：观察对话体验，再决定 Opus 上行 / Jitter buffer
4. **第 4 步（不做）**：ESP-ADF 重构

---

## 10. 关键引用清单（绝对路径）

### Kapi_Rtc_toy 项目内
- `main/CMakeLists.txt:235-239` — RTC 模式宏定义
- `main/protocols/volc_rtc_protocol.cc:394-407` — CloseAudioChannel 只 stop 不 destroy
- `main/protocols/volc_rtc_protocol.cc:32-34` — volc_rtc_destroy 已被析构函数调用，提取 LeaveRoom 极容易
- `main/application.cc:1961-2042` — Dialog Watchdog 当前用 esp_restart()
- `main/application.cc:2161` — 唯一的 last_audible_output_time_ 刷新点（方案 A）
- `main/application.cc:1321` — subtitle 分支位置（方案 B 插入点）
- `main/audio/simple_pipeline.cc:1-60` — codec 直写 stub，确认非 ESP-ADF
- `main/audio_codecs/box_audio_codec.cc:67` — ES7210 mic_selected
- `main/boards/movecall-moji-esp32s3/config.h:27` — `AUDIO_INPUT_REFERENCE 0`
- `main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc:1507-1521` — BoxAudioCodec 创建
- `sdkconfig:642-645` — AUDIO_PROCESSOR 未启用
- `main/audio_processing/audio_processor.h:41-90` — AudioProcessor 已完整实现，等启用
- `main/idf_component.yml:8` — esp-sr ^2.0.3 已声明
- `05-最新日志.txt:160` — 房间名 `aibotrtc_G711A_*` 确认下行 G711A
- `03AEC_VOICE_INTERRUPT_PORTING_PLAN.md` — AEC 移植规划（计划未实施）

### Baji_Rtc_Toy 衍生项目交叉引用
- `/Users/rdzleo/Desktop/Baji_Rtc_Toy/docs/Rtc_AIavatar/RTC软退出方案_移植参考.md` — Phase 6 完整移植参考（手把手）
- `/Users/rdzleo/Desktop/Baji_Rtc_Toy/docs/Rtc_AIavatar/官方Korvo2方案_对比分析报告.md` — 包含与官方 Korvo-2 的全方位对比、ES7210 AEC 电路分析、决策记录
- `/Users/rdzleo/Desktop/Baji_Rtc_Toy/.planning/milestones/digital_human_rtc/phases/phase_06_idle_hibernate/PLAN.md` — Phase 6 实施计划
- `/Users/rdzleo/Desktop/Baji_Rtc_Toy/.planning/milestones/digital_human_rtc/phases/phase_07_battery_psm/README.md` — Phase 7 占位规划

---

## 11. 一句话总结

> **Kapi_Rtc_toy 是 Baji_Rtc_Toy 的"无屏轻量版底座"**。Phase 6 软退出方案 100% 可移植且工作量极小（仅显示提示需替换为 LED/语音）；AFE-AEC 资源富余但需先确认硬件 REF 通道；**坚决不推荐**重构成 ESP-ADF。

---

## 附录·重要提醒

🎯 **Kapi 是更合适的 AFE 实验场地**

Baji_Rtc_Toy 项目目前 internal SRAM 仅剩 **44KB**（参见 Baji 项目 `docs/Rtc_AIavatar/官方Korvo2方案_对比分析报告.md` §11.2），启用 AFE 后将仅剩 9KB，**几乎必然导致开机崩溃**。

而 Kapi_Rtc_toy 项目 internal SRAM 余量 **80-130KB**，启用 AFE 后仍有 **50-100KB 安全余量**。

**结论**：未来如要验证 ESP-SR AFE 启用方案，**应该优先在 Kapi 项目实验**，跑通后再回到 Baji 评估资源能否承载。
