d4362311cc
feat(badge-ui): 电子吧唧 Home 背景图切换为 jahub360 + 资源同步
...
1. 电子吧唧 Home 界面背景图从 ui_img_airhub_png 切换为
ui_img_jahub360_png(360×360 全屏,尺寸一致):
- main/CMakeLists.txt:编译条目改为 ui_img_jahub360_png.c
- main/ui/ui.h:LV_IMG_DECLARE 声明切换
- main/ui/screens/ui_ScreenHome.c:lv_img_set_src 使用新图源
- main/ui/images/ui_img_jahub360_png.c:新增 SquareLine 导出资源
- 旧 ui_img_airhub_png.c 保留在仓库,未删除可随时回退
2. spiffs_image 资源同步:
- 02.jpg / default.jpg 替换为新版图片
- 新增 spiffs_image_backup/(Elf-circle / Standby_Norm 240×240
EAF 资源备份)
3. sdkconfig 同步 ESP-IDF 自动重生成的 SOC/camera/phy 配置差异
(非手动改动,保持构建一致性)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 15:54:56 +08:00
7b322cccbd
docs: 补充双模式资源优化分析
2026-06-04 14:59:31 +08:00
55da5297ee
feat: expand badge image storage capacity
...
1. 将电子吧唧 SPIFFS 图片列表上限从 10 张提升到 100 张。
2. 缩小 factory app 分区到 0x700000,并将 storage SPIFFS 扩大到 0x8F0000,用于更多 APP 图传图片。
3. 新增电子吧唧 GIF 图传转 EAF 方案分析文档,沉淀 GIF 限制、服务器转换和 APP 离线转换路线。
4. 同步最新烧录与 APP 图传测试日志,记录 6 张图传图片和容量验证过程。
2026-06-02 15:39:10 +08:00
6b166f4463
feat: add EAF RTC and badge dual mode
...
1. 固定 RTC 数字人链路使用 ai_chat_ui_eaf,双模式开启后不再回退 LVGL/GIF 旧 RTC UI。
2. 保留电子吧唧 LVGL/SquareLine UI,只在电子吧唧运行模式启动 LVGL,避免与 EAF 抢同一 LCD flush。
3. 拆分 dzbj_hw_display_init 与 dzbj_display_init,AI/配网只初始化 LCD Touch 硬件,电子吧唧再启动 LVGL UI。
4. 配网模式使用 EAF 最小显示栈显示中文提示,请使用APP 蓝牙配网,不加载数字人资源和动画。
5. 开启 CONFIG_BAJI_BADGE_MODE,形成 RTC 数字人对话与电子吧唧图片显示双模式固件。
6. 电子吧唧图片扫描跳过 Background_360x360.jpg,避免 RTC 数字人背景进入吧唧图片列表。
7. BLE 图传在 BLE 5.0 关闭时跳过 2M PHY API,保持 legacy 1M PHY 兼容配网和图传。
8. sdkconfig.defaults 同步 BLE 内存优化,限制连接数和缓存,保留 GATT 与扫描能力。
9. 移除 ota.cc 编译和 app_update 直接依赖,双模式固件不创建 OTA 检查任务。
10. Ota 接口改为禁用 stub,保留接口兼容但不执行升级和版本检查。
11. Board 上报 JSON 的 OTA label 改为 disabled,避免依赖 OTA 运行分区。
12. partitions.csv 改为 factory 单 app 分区,扩大 app 到 0x900000,并扩大 storage 到 0x6F0000。
13. application 去除 OTA 任务句柄和服务器时间依赖,减少运行时资源占用。
14. system_info 去除 esp_ota_ops 依赖,配合无 OTA 分区配置。
15. 同步最新烧录运行日志,记录本轮双模式与配网测试结果。
2026-06-02 13:16:39 +08:00
24e0d19d29
fix(config): 对齐 Baji RTC 衍生项目配网配置
...
1. BLE / RTC 默认配置
- 开启 CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST,让 Bluedroid host 动态分配优先走 PSRAM
- 关闭 CONFIG_BT_BLE_50_FEATURES_SUPPORTED,数字人 RTC 与 BLE 配网继续使用 legacy advertising
- 增加 CONFIG_LWIP_MAX_SOCKETS=20,给火山 RTC ICE/socket 建连预留 fd
- 保持 BluFi 关闭,项目继续使用自定义 GATT 配网服务
2. ESP32-S3 PSRAM defaults
- 开启 CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
- 开启 CONFIG_SPIRAM_ALLOW_NOINIT_SEG_EXTERNAL_MEMORY
- 将 BT/WiFi/LWIP 的静态段迁移到 PSRAM,释放内部 SRAM 给 BLE controller 和 RTC
3. 实机测试记录
- 更新 05-最新日志.txt,记录配网模式启动、BLE controller feature、EAF/音频初始化和复位现象
- 保留串口原始日志格式,便于后续对比 BLE 配网行为
4. 本地开发配置
- 更新 VSCode ESP-IDF 串口为 /dev/tty.usbmodem834401,匹配当前测试设备
2026-05-29 13:53:55 +08:00
bffd31645e
feat(provisioning): BLE 配网完整修复 (跳过 EAF 资源 + EAF 最小化 + 音效播放)
...
修复 4 个配网模式核心问题, 让 Rtc_AIavatar 分支 (含火山 RTC SDK + 软件 AEC + 完整业务)
能像 adaptation_dzbjImg_shar 一样正常配网, 同时显示居中提示文字.
============ 问题与修复 ============
### 问题 1: 配网模式 BLE 广播 ADV_DATA malloc 失败 (手机搜不到设备)
日志:
E (3731) BLE_INIT: Malloc failed
E (3731) BT_HCI: CC evt: op=0x2008 (HCI_BLE_WRITE_ADV_DATA), status=0x7
I (3731) BluetoothProvisioning: ✅ 广播启动成功 (假成功, 广播数据空)
根因:
Rtc_AIavatar 比 adaptation_dzbjImg_shar 多 ~50-80 KB DRAM 业务 .bss
(软件 AEC + HTTPS 完整状态机 + dialog watchdog + 完整 RTC 状态),
+ 火山 RTC SDK 静态库 .bss ~30-50 KB (g_cnxMgr 14.6KB, ack$14 12.6KB 等),
配网模式时 BLE Bluedroid stack 抢不到广播数据 malloc 所需的 ~10KB DRAM.
修复 (前次 commit 已做): sdkconfig 关闭 BLE 5.0 6 个特性 (项目实际只用 4.2 legacy),
省 ~15 KB controller DRAM, 广播数据 malloc 成功.
### 问题 2: 配网模式下 LCD 绘制跟 WiFi/BLE 初始化抢 DRAM 导致 reboot
日志:
E (1200) wifi:Expected to init 10 rx buffer, actual is 1
E (1220) BluetoothProvisioning: WiFi初始化失败: ESP_ERR_NO_MEM
assert failed: vQueueDelete queue.c:2355 (pxQueue) ← BLE GATT fixed_queue_new 失败 → 反向清理 NULL 队列
排查路径 (失败方案记录):
- esp_lcd_panel_draw_bitmap 一次画 360x360 (253KB): SPI queue 满, 下半屏未画 + DRAM 抢 WiFi
- 分块画 (60 行/块) + vTaskDelay 块间: SPI driver 内部 queue 持续保留 DRAM, 仍然抢
- 强制 codec output_only=false 完整 duplex: 多 15KB DRAM, BLE BTU_StartUp malloc 失败 reboot
- CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=y: 引入 BTU bt_workqueue 分配失败 → vQueueDelete NULL → assert
修复 (本次 commit): EAF 最小化初始化
movecall_moji_esp32s3.cc 配网模式调用新增的 ai_chat_screen_init_provisioning(),
跳过 8 张 EAF 资源加载 (省 4.32 MB PSRAM + ~10KB DRAM), 跳过数字人 anim,
只启用 gfx_emote renderer + 单个 gfx_label, flush buffer 启动时预分配 (~30KB DRAM 一次到位),
跟 BLE 初始化不再有动态分配冲突. 跟 adaptation_dzbjImg_shar 用 LVGL 显示 GIF 同思路,
用 EAF 替代 LVGL 避免引入 50-80KB LVGL .bss.
### 问题 3: 配网模式音效不播放
根因:
ResetWifiConfiguration 由 BOOT 按键 OnClick 调用, 跑在 esp_timer task 上下文,
vTaskDelay(4000ms) 实测只等了 1.1 秒就被唤醒, 音效没播完就 esp_restart.
修复 (前次 commit 已做): 派发到独立 task 跑 PlaySound + vTaskDelay + esp_restart,
独立 task 中 vTaskDelay 正常工作, 等 4 秒确保 解码 + DMA + 功放尾音完整.
### 问题 4: 配网时屏幕黑屏 (UX 不友好)
实施: ai_chat_screen_init_provisioning("请使用APP\n蓝牙配网~")
LCD 黑底白字居中显示提示文字, 用户感知"配网中".
label height=64 (恰好包 2 行 + 余白), GFX_ALIGN_CENTER 上下左右居中.
============ 文件改动 ============
main/application.cc:
Application 构造时显式注释: 不能在配网模式置 background_task_=nullptr
(OnAudioOutput 无判空, 会 std::mutex::lock 异常 abort).
main/boards/common/wifi_board.cc:
ResetWifiConfiguration 派发独立 task 跑 PlaySound + 4s delay + esp_restart,
EnterWifiConfigMode BLE 启动后早 return (StartBleProvisioning 内部已 Alert 音效).
main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc:
AI 对话模式分支: 配网时调 ai_chat_screen_init_provisioning() 显示文字,
正常模式调 ai_chat_screen_init() 显示数字人.
main/dzbj/ai_chat_ui.h:
新增 ai_chat_screen_init_provisioning(const char* hint_text) 声明.
main/dzbj/ai_chat_ui_eaf.c:
新增 ai_chat_screen_init_provisioning() 实现, EAF 最小化路径:
gfx_emote_init + gfx_disp_add + 单 label 显示文字, 跳过 EAF 资源/anim/背景图.
============ 测试结果 (设备实测) ============
- 按 BOOT 触发配网: 听到完整配网音效 (P3_LALA_WIFICONFIG 约 1 秒)
- 设备重启 → 配网模式启动 → LCD 显示"请使用APP\n蓝牙配网~" 居中
- 手机能搜到 Airhub_d0:cf:13:03:bb:f2 → 能连接 → 配网完成
- 配网完成重启 → 正常模式数字人 + RTC 对话功能正常
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 14:42:13 +08:00
2458c4e8bc
fix(ble): 关闭 BLE 5.0 特性释放 controller DRAM, 修复配网广播数据 malloc 失败
...
问题:
日志:
E (3731) BLE_INIT: Malloc failed
E (3731) BT_HCI: CC evt: op=0x2008 (HCI_BLE_WRITE_ADV_DATA), status=0x7
E (3731) BLE_INIT: Malloc failed
E (3731) BT_HCI: CC evt: op=0x2009 (HCI_BLE_WRITE_SCAN_RSP), status=0x7
I (3731) BluetoothProvisioning: ✅ 广播启动成功
代码层"广播启动成功", 但 HCI 层 ADV_DATA + SCAN_RSP_DATA 都没写入 → 广播空数据 → 手机搜不到设备.
根因:
sdkconfig 同时启用了 BLE 5.0 + 4.2 全套特性, 但项目代码实际只用 4.2 legacy advertising
(esp_ble_adv_params_t / esp_ble_gap_start_advertising). BLE 5.0 6 个特性总和占用 controller DRAM,
让 HCI ADV_DATA / SCAN_RSP_DATA 内存池耗尽.
修复:
sdkconfig 关闭所有 BLE 5.0 特性 (项目实际不用):
# CONFIG_BT_BLE_50_FEATURES_SUPPORTED is not set
# CONFIG_BT_BLE_50_EXTEND_ADV_EN is not set
# CONFIG_BT_BLE_50_PERIODIC_ADV_EN is not set
# CONFIG_BT_BLE_50_EXTEND_SCAN_EN is not set
# CONFIG_BT_BLE_50_EXTEND_SYNC_EN is not set
# CONFIG_BT_BLE_50_DTM_TEST_EN is not set
保留 CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y (legacy advertising 必需).
dzbj_ble.c:458 用了 esp_ble_gap_set_preferred_phy (BLE 5.0 API), 但有
#if (BLE_50_FEATURE_SUPPORT == TRUE) 保护, 关闭后编译自动跳过, 不影响其他功能.
附加: 修复 BOOT 触发配网时音效不响
wifi_board.cc::ResetWifiConfiguration():
- 移除直接 vTaskDelay (iot_button 回调跑在 esp_timer task, 实测 vTaskDelay 4000ms 只等了 1.1s)
- 改用 xTaskCreate("wifi_reset") 独立 task 跑: PlaySound + vTaskDelay(4000) + esp_restart
- 在重启前播完配网音效
wifi_board.cc::EnterWifiConfigMode():
- 移除之前在 BLE 配网成功后重复 PlaySound 的代码 (StartBleProvisioning 内部 Alert 已经调用过)
注: codec output_only 仍保持 NeedsProvisioning() (TX-only + ES8311-only).
强制 duplex 会让 BLE Bluedroid gatt_init malloc failed → assert reboot loop, 已验证.
待解决 (留待 adaptation_dzbjImg_shar 分支对比):
- 关闭 BLE 5.0 后手机可搜到设备, 但点击连接失败
- 配网模式下 P3_LALA_WIFICONFIG 音效仍不响 (StartBleProvisioning 内 Alert 调用但 audio_loop 似乎没消费)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 12:02:44 +08:00
70f0cdd07a
feat(rtc): 偶发连接失败完整修复 (A+B+C 三件套)
...
实测根因 (DIAG 埋点确认): 火山 RTC SDK 启动时一次性申请大量 lwIP socket fd,
默认 CONFIG_LWIP_MAX_SOCKETS=10 不够 SDK 分配, 触发 SocketConnection-Lite.c:191
bind local ip failed → ICE 协商失败 → wait connect bits=0x0 超时.
实测对比:
修复前: 冷启动 RTC join 30+ 秒超时 × 3 次失败
修复后: 冷启动 RTC join 1.6 秒成功, 软退出 + 唤醒重连 2.3 秒成功 ✅
修复内容:
[A] sdkconfig: CONFIG_LWIP_MAX_SOCKETS=10 → 20
根治 lwIP socket fd 不足. 16 是临界值, 20 留 25% 余量应对 burst 场景
(HTTP 重试 / DNS 查询 / NTP 同步并发). 代价: +6 fd × ~200B = 1.2 KB RAM (忽略).
[B] application.h/cc + volc_rtc_protocol.h/cc: 失败 3 次后销毁 + 重建 engine
新增 VolcRtcProtocol::ForceRebuildEngine() public 方法.
OpenAudioChannel 连续失败 3 次时调用 (application.cc:566-573):
- 销毁 rtc_handle_ + reset SDK 内部状态污染
- 等待 2 秒让 lwIP 释放残留 socket fd (TIME_WAIT)
- 触发 Phase 6 重建路径 (rtc_handle_=nullptr → Start())
应对 A 修复后仍可能出现的 SDK 内部状态错乱 (e.g. ICE Agent 异常).
本次实测未触发 (A 已解决主要问题), 但保留作为兜底防御.
[C] volc_rtc_protocol.cc: DIAG_RTC_BIND_ENABLE 一键开关诊断埋点
在 join_room 前/后 + ForceRebuildEngine 前/后打印:
- lwIP socket fd 使用量 (sockets=N/MAX)
- heap free + psram free
- WiFi rssi
- 失败时的 errno + strerror
验证完成后改 0 关闭, 编译器消除 #if 块, 零运行时开销.
文件改动:
sdkconfig | LWIP_MAX_SOCKETS 10→20
main/application.h | +audio_channel_retry_count_
main/application.cc | +重试计数 + static_cast → ForceRebuildEngine 调用
main/protocols/volc_rtc_protocol.h | +ForceRebuildEngine() 声明
main/protocols/volc_rtc_protocol.cc | +DIAG 埋点 + diag_count_used_sockets() + ForceRebuildEngine()
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 10:23:21 +08:00
3e709577f5
docs: 更新 Claude Code 插件高效运用指南 (加 embed-ai-tool 3 个嵌入式 skill)
...
补充内容:
- 一、资源总览: 新增 "embed-ai-tool 嵌入式专项 Skills (3 个)" 行
- 五、自动触发表: 加 serial-monitor / rtos-debug / static-analysis 触发关键词
- 五、协同表: 加 embed-ai-tool 与插件配合的工作流
- 八、新电脑环境恢复指南:
* 新增步骤 3.1.5 安装 embed-ai-tool 3 个 skill (git clone + cp)
* 8.3 恢复内容清单新增 embed-ai-tool 行
* 可选依赖工具说明 (pyserial / cppcheck / llvm)
3 个 skill 用途:
- serial-monitor: 串口抓包/日志分析 (避免手动复制粘贴日志)
- rtos-debug: FreeRTOS 任务/栈/死锁分析
- static-analysis: cppcheck/clang-tidy/MISRA-C 静态扫描
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:17:54 +08:00
b7ee0f9885
chore(docs): 数字人 GIF 资源更新 (ezgif 处理后 + Cubism 工程同步)
...
新增 Ezgif_Export/ 目录, 存放 8 张 ezgif 处理后的 GIF (240×320 + 抽帧 N=3),
这些是直接喂给在线 EAF Packer 的源文件, 跟 spiffs_image/hiyori-assets.bin 对应.
也包含 m03/m05 源 GIF 更新 (m05 从 7 MB 优化到 1.9 MB, ezgif resize) 和
Cubism 工程 hiyori_free_t03.can3 同步.
ezgif 处理参数 (实测最优):
- Resize: 240×320 + ImageMagick + coalesce (撤销优化) + 添加透明内边距
- Frames: Every 3 + Skip every N-th (-33% 帧数)
- Converter: libvips (无 dithering)
- Effects: don't stack frames ✓
EAF Packer 配置:
- 屏幕: 240×320 矩形 + 背景色 #000000 (chroma key 必须黑色)
- 命名: hiyori_m01 ~ hiyori_m08 (跟代码 emotion_map 对齐)
- 循环模式: 双点循环 [0, 末帧]
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:17:39 +08:00
be788be251
feat(ui): 8 张 EAF 数字人完整接入 (m01~m08 全情绪映射)
...
数字人从原本 m06+m07 两张 EAF 扩展到 m01~m08 八张, 通过 ezgif 240×320 +
抽帧 N=3 + EAF Packer 配置, 8 张 EAF 总和压缩到 4.32 MB, SPIFFS 当前
4.94 MB 分区直接装下, 无需扩分区也不丢 OTA 升级能力.
main/dzbj/ai_chat_ui_eaf.c:
- 新版/旧版 MMAP 自动检测 (header[8] == 0x14 → entry 32B; 0x10 → 28B),
兼容在线 EAF Packer 两种导出格式 (FSIZE/FOFFSET 偏移自动适配).
- find_cache_index_by_name 加 fallback: 找不到精确匹配时返回 cache[0],
PoC 阶段单张 EAF 也能验证全部情绪触发.
- emotion_map 22 情绪 → 8 张 EAF 重排:
* 默认/积极组 12 → m01..m05 均分 (每张 2-3 种)
* 思考/疲倦组 5 → m06
* 负面/严肃组 3 → m07
* 惊讶组 2 → m08
- 数字人对齐 GFX_ALIGN_CENTER → GFX_ALIGN_BOTTOM_MID, 240×320 在
360×360 圆屏贴底显示, 顶部 40px 透明露出背景图, 视觉跟之前
360×360 全屏 EAF 一致 (脚部贴底, 字幕 z-index 上层覆盖底部 56px).
spiffs_image:
- hiyori-assets.bin: 956 KB (m06+m07) → 4.53 MB (m01~m08 + index.json)
- 删除原 GIF (hiyori_m{03,06,07}.gif), EAF 已替代不需要烧到设备.
实测数据 (Baji 2026-05-20):
m01=814KB m02=516KB m03=563KB m04=559KB m05=606KB m06=423KB m07=379KB m08=566KB
8 张 EAF 总和: 4.32 MB
SPIFFS 占用: 4.58 MB / 4.64 MB 可用 = 1.3% 余量 (临界, 未来加资源需要规划)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 18:17:09 +08:00
c6ecdb124c
feat(audio): 同步 Kapi 软件 AEC + NULL crash fix 到数字人项目
...
来源: Kapi commit 63b21fd (NULL fix) + a369796 (软件 AEC) 完整移植
改动:
- components/common/src/volc_rtc.c
on_global_error 加 message ? message : "(null)" 防御.
解决: idle ≥10 分钟后服务端 session 超时 / NAT 表过期触发的
printf("%s", NULL) → strlen panic → 设备重启.
- main/CMakeLists.txt
REQUIRES 末尾加 esp-sr (提供 esp_aec.h 同步 API).
- main/application.h
+7 个 AEC 成员 + 5 个函数声明 (recorder/player pipeline 后).
- main/application.cc
+InitAec / DeinitAec / AppendRefSamples / GetDelayedRef / ApplyAEC (~170 行).
OnAudioOutput 三个 codec output 位置都加 AppendRefSamples hook.
ReadAudio 两条路径 (recorder_pipeline + codec 直读) 加 lazy InitAec
+ ApplyAEC + target_samples = max(samples, chunk_size).
PHASE8_DIAG_ENABLE 默认 0 (诊断埋点已完成根因定位, 关闭减少日志噪声).
实测效果 (30 分钟设备验证):
AI 说话: mic=285 ref=8310 clean=31 (消除 89%)
AI 说话: mic=660 ref=7489 clean=57 (消除 91%)
AI 说话: mic=156 ref=2748 clean=0 (消除 100%)
用户说话: mic=224 ref=8 clean=224 (passthrough 正常)
资源占用:
Flash +59 KB (+1.2%)
Internal SRAM +35-50 KB (+10-15%)
PSRAM +10-15 KB (<0.2%)
Core 1 CPU +6-12% @240MHz
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 16:54:55 +08:00
22b7a70d7d
fix: 同步 Kapi 软 RTC 退出五连修到数字人项目(待命音 + 欢迎语杂音)
...
从 Kapi commit b1577d8 / a3a476f 完整移植 5 个修复,覆盖三类问题:
1. 开机/唤醒后按 BOOT 进 RTC 房间,欢迎语前 1-3 秒杂音
2. 软 RTC 退出(41s 无对话触发 Dialog watchdog)后待命音"卡卡正在待命"无声/杂音/被截
3. 软退出后按 BOOT 唤醒,欢迎语前杂音
【修复 1】OnAudioChannelOpened EnableOutput(true) 后立刻灌 200ms silence
- 防止 I2S DMA 启动后到 RTC 真实 PCM 到达 1-3s 空窗的杂音
【修复 2】LeaveRoom 加 notify_closed 参数(默认 true 不变老路径)
- hibernate 路径传 false 跳过 on_audio_channel_closed_ 回调
- 避免回调链 player_pipeline_close → EnableOutput(false) 误关 codec
导致待命音无声
【修复 3】LeaveRoom 不再 volc_rtc_destroy, 保留 rtc_handle_
- 唤醒时 OpenAudioChannel 直接 volc_rtc_start 复用 handle, 不死循环
- 服务端 AI 任务无需 destroy 也会按 180s 兜底机制清理
【修复 4 - 最隐蔽】LeaveRoom 末尾重置 downlink_is_pcm_ = false
- 火山 RTC 下行是 PCM, DataCallback 设 downlink_is_pcm_=true
- 不重置 → PlaySound 的 Opus 包被 OnAudioOutput 当成 raw PCM 字节流
直接写 codec → 杂音而非待命音
- 唤醒重连后 DataCallback 收下一包会自动重置, 不影响欢迎语
【修复 5】OnAudioInput 入口加 hibernating_ guard
- hibernate 期间禁用输入侧, 防止访问关闭的 codec → std::bad_alloc abort
- 不冻结 OnAudioOutput, 让待命音队列正常被消费
【EnterIdleHibernate 重写】套用 Kapi 新顺序:
Step 0: hibernating_=true + 50ms (让 OnAudioInput guard 生效)
Step 1: LeaveRoom(false) (codec output 保留)
Step 2: background_task->WaitForCompletion
Step 3: 清空 audio_decode_queue_
Step 4: EnableInput(false) + close recorder_pipeline
Step 5: 强制 esp_pm 禁用 Light Sleep
Step 5.5: EnableOutput(false→true) + 200ms silence (清 LeaveRoom 副作用)
Step 6: SetDeviceState(idle) → PlaySound 待命音
Step 7: WaitForAudioPlayback (队列消费完毕)
Step 7.5: background_task->WaitForCompletion + vTaskDelay(1000)
(DMA + ES8311 FIFO + 功放尾音衰减, 防尾音截断)
Step 8: player_pipeline_close
Step 9: NVS idle_cycles_++
Step 10: 显示字幕"已自动退出RTC对话..."(数字人特有, 保留)
【WakeFromHibernate】调整 hibernating_=false 顺序
- 先放下 hibernating_, 让 ToggleChatState 期间 OnAudioInput guard 通过
- 否则 ToggleChatState 期间音频上行迟迟不开
编译: kapi.bin 0x41c000 (4.21MB), 分区 25% 空闲。
实测三项全通: 欢迎语干净 + 待命音清晰完整 + 唤醒欢迎语干净。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 10:11:36 +08:00
eceadda807
feat(ui): Phase 10 step 1+2 - 背景图 + 中文字幕 + 数字人透明
...
完成数字人模式 UI 的"背景图叠加 + 实时字幕"功能。所有改动基于 EAF
框架(Phase 10 commit 31982ba),保持 0 个 lv_* UI 函数链接进固件。
Step 1: JPG 背景图叠加
- ai_chat_ui_eaf.c 加 esp_jpeg 解码 Background_360x360.jpg →
RGB565 buffer (252KB PSRAM) → gfx_img_create 作为底层
- z-index 通过创建顺序控制: 背景 → 数字人 anim → 字幕 label
- 选项 A 保留 JPG (~20KB SPIFFS) 比选项 B (252KB .bin) 省 232KB
数字人透明: esp_emote_gfx local patch (gfx_anim.c::gfx_anim_render_24bit_pixels)
- 根因: 在线 EAF Packer 默认导出 24-bit 模式,工具不暴露 bit_depth
选项,alpha 滑块拉到 0 无法保存,导致 GIF 透明像素被烘焙成屏幕背景
色 (黑色 RGB888 #000000 )
- 解决: 在 24-bit 渲染函数加 chroma key,跳过近黑像素让背景图露出
- 阈值演化 v1 (0x0000) → v3 (16) → v4 (24),最终 RGB888 ≤ (24,24,24)
- 保留 R/G/B AND 关系(三分量都小才透明),保护数字人本体暗色不破洞
- 双字节序判定,兼容 disp_config_t.flags.swap = true
Step 2: 中文字幕 (gfx_label + LVGL bitmap font 方案 A)
- 字体方案对比 3 方案后选方案 A(C 数组 XIP from Flash):
• A: 1.4MB Flash + 0 RAM (推荐)
• B: xiaozhi-fonts .bin 1.18MB SPIFFS + 1.18MB PSRAM
• C: 自转 .bin ~2.8MB 总占用
- extern const lv_font_t font_puhui_20_4 → gfx_label_set_font 直接喂
- linker 副作用: 仅引入 7 个 LVGL 函数 ~2.2KB(lv_font_get_bitmap_fmt_txt
/ lv_mem_* 幽灵符号),无 lv_obj/lv_disp/lv_indev 等 UI 框架函数
- 字幕参数: 300×56 (2 行限制) + 行间距 4 + 贴底 y_ofs=-4
- GFX_LABEL_LONG_WRAP 字符级断行(中文友好),CENTER 居中
- 流式 TTS 节流 50ms(比 LVGL 100ms 短,EAF 渲染更快)
工具脚本 (tools/patch_eaf_transparency.py)
- 探索性脚本:解析 hiyori-assets.bin 尝试修补 EAF palette alpha
- 实际未生效(工具导出 24-bit 无 palette),保留作为 EAF bin layout
解析参考
固件大小: 2.75MB → 4.30MB(+1.55MB = 字体 1.4MB + 字幕代码 + 背景图代码)
分区余量: 50% → 25% (1.42MB 空闲,安全)
完整踩坑经验已沉淀到 ~/.claude/CLAUDE.md §13 + 项目 memory。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 17:38:31 +08:00
4de9f2ba61
feat(assets): 添加 hiyori-assets.bin(Phase 10 EAF 数字人资源包)
...
ESP Emote GFX Packer 在线工具(emote-gfx-gen-tool-dev.pages.dev)
打包产物,含:
- index.json (286 B): 表情元数据
- hiyori_m06.eaf (505 KB): 默认/积极情绪动画
- hiyori_m07.eaf (450 KB): 思考/疲倦情绪动画
(m03 待补,sad/angry 暂用 m07 fallback)
sdkconfig 同步: 新 esp_emote_gfx Kconfig 选项的默认值
(HEATSHRINK + JPEG decode + tri-edge AA 等)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:56:33 +08:00
0d0bc33192
chore(deps): managed_components 自动更新
...
idf.py reconfigure 触发的 idf-component-manager 版本刷新副作用:
- espressif/dl_fft, esp_jpeg, freetype 等组件的小版本更新
不影响项目功能,与 Phase 10 无直接关系。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:56:33 +08:00
86200f5e3a
chore(deps): 添加 esp_emote_gfx + esp_mmap_assets 组件(Phase 10 依赖)
...
Phase 10 数字人模式 LVGL → EAF 切换所需的两个新组件:
- espressif2022/esp_emote_gfx v3.0.5
轻量软件渲染 UI 框架(gfx_emote_init/gfx_disp_add/gfx_anim/gfx_label)
- espressif/esp_mmap_assets v2.0.0
资源打包加载(虽然 use_fs 模式 buggy,我们绕过它直接 fopen,
但保留组件以便后续 mmap partition 模式启用)
gfx_touch.c 含我们的 local shim 兼容 esp_lcd_touch v1.1.2 旧 API
(已在前一个 commit 31982ba 中说明)。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:56:32 +08:00
31982ba7b9
feat(ui): Phase 10 - 数字人模式 LVGL → esp_emote_gfx 完整切换
...
✅ 验证完成:
- 音频卡顿明显改善(用户实测)
- 数字人 hiyori 动画正常显示
- nm 验证:固件中 0 个 lv_*/lvgl_* 函数符号
- kapi.bin: 4.7MB → 2.75MB(-42%)
关键改动:
- main/dzbj/ai_chat_ui_eaf.c (404 行新增):
完全替代 LVGL 版 ai_chat_ui.c,提供同名 C API(ai_chat_screen_init
/ set_status / set_emotion / set_chat_message / resume_animation)。
AiChatDisplay C++ 桥接层无需改动。
内部用 gfx_emote_init + gfx_disp_add + gfx_anim + mmap_assets。
- main/CMakeLists.txt:双轨编译
CONFIG_BAJI_BADGE_MODE=y → ai_chat_ui.c (LVGL) + bg_gif_demo.c
CONFIG_BAJI_BADGE_MODE=n → ai_chat_ui_eaf.c (esp_emote_gfx)
- main/dzbj/dzbj_init.c:EAF 模式跳过 lvgl_lcd_init() 调用
- main/dzbj/lcd.c/h:暴露 lcd_io_handle 给 EAF 注册 IO 完成回调
踩坑修复(commit message 留档供后续参考):
1. esp_mmap_assets v2.0.0 在 use_fs=true 模式下 mmap_assets_get_mem()
返回的是文件内偏移量而非 RAM 指针(fseek bug + offset 没加
data_section_start),导致 LoadProhibited panic。
解决:完全绕过 mmap_assets,自己 fopen + 解析 MMAP bin 头
(layout: 头 16B + 每 entry 28B + data 段每文件 2B magic + 数据)。
2. esp_emote_gfx 期望 esp_lcd_touch v2.x 新 API,项目用 v1.1.2 旧 API。
在 managed_components 内 gfx_touch.c 加 shim 桥接(local patch,
reconfigure 后需 reapply)。
3. EAF format magic 是 0x89 'EAF'(gfx_eaf_dec.h),不是 0x5A5A
(那是 esp_mmap_assets 内部文件分隔符)。
4. SPIFFS 需要在 ai_chat_screen_init 入口自动挂载(不能依赖
bg_gif_demo 的惰性挂载,那个已被 CONFIG 排除)。
依赖增量:
- espressif2022/esp_emote_gfx: ~3.0.5
- espressif/esp_mmap_assets: * (仅用于声明依赖,运行时被绕过)
数字人模式核心 UI 范围:
- 显示数字人动画 ✅ (hiyori_m06/m07, 居中循环)
- 情绪 → GIF 映射 ✅ (23 情绪 → 2 EAF,sad/angry 暂用 m07,m03 待补)
- 字幕/状态文字: stub ⏳ (字体接驳留待后续,需打包 .bin 字体到资源)
- 触摸: 不支持(PoC 阶段不需要)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 15:53:21 +08:00
3a1111e99d
plan(rtc-only): Phase 9 取消 + Phase 10/11/12 规划(LVGL → esp_emote_gfx)
...
Phase 9 三轮增量优化(jitter buffer / codec init / Core 1 绑定)效果不
明显,用户决策完整切 EAF 验证 GIF 抢资源假设。
Phase 9 → CANCELLED:
- v1 jitter buffer device_state 判错(漏 kDeviceStateDialog)
- v1 ES7210 重试破坏 ES8311 init 导致开机播报无声
- v2 修正 device_state 后 jitter 工作但仍卡
- v3 background_task 绑 Core 1 + DIAG-5 未硬件验证
- 所有代码改动 git restore 回滚(无 commit),Phase 8 DIAG 埋点保留
- CANCELLED.md 记录教训
Phase 10 新增(数字人模式 LVGL → esp_emote_gfx 完整切换):
- 添加 espressif2022/esp_emote_gfx ~3.0.5 依赖(已 reconfigure 拉取)
- API 风险扫清:GFX_LABEL_LONG_WRAP 支持中文换行、
gfx_font_lv_load_from_binary 兼容 LVGL bitmap font
- 双轨编译:CONFIG_BAJI_BADGE_MODE=y 保 LVGL,=n 走 EAF
- PLAN.md 含 10 个子任务从依赖到完整 UI 切换
- 预估 3-5 天
Phase 11 占位:LVGL 释放的 ~40KB DRAM + ~80KB PSRAM 投到 WiFi
缓冲扩容(STATIC_RX 10→16、DYN_RX/TX 32→48、RX_BA_WIN 6→16)+
Opus/RTC SDK jitter buffer 扩容
Phase 12 占位:原 Phase 10 集成测试 + 推送,重编号
ROADMAP 同步更新,依赖关系矫正。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 13:37:34 +08:00
3dc6cadf49
diag(rtc-only): Phase 8 - 音频卡顿根因诊断埋点 + 数据采集报告
...
数字人 RTC 模式音频卡顿根因定位。通过 4 类 ESP_LOGW 埋点采集运行时
数据,对照表格判定根因,输出 Phase 9 实施分支决策。
埋点实现(main/application.cc,PHASE8_DIAG_ENABLE 宏开关,关闭后零开销):
- DIAG-1 queue 深度:3 处(出队 + WebSocket 入队 + RTC 入队),50ms 节流
- DIAG-2 codec->OutputData 写入耗时:>15ms 阈值告警
- DIAG-3 WiFi RSSI:OnClockTimer 1Hz
- DIAG-4 heap 快照 + 碎片率:OnClockTimer 1Hz
实测结论(见 DIAG_REPORT.md):用户感知卡顿 = 两个独立根因
- A. 开机播报阶段 ③' codec init 时序缺陷(ES7210 I2C 失败 +
126 次 write_slow 集中在 2-13s)
- B. RTC 对话阶段 ⑤ Opus/WebSocket 应用层帧到达抖动
(queue 突发堆积 19 + queue=0 出现 58 次,但 codec 写入 0 次 slow)
完全排除:① CPU 争抢、② PSRAM 带宽、④ WiFi 丢包(RSSI -24~-33dBm
极强)、⑥ 内存碎片(heap 全程稳定)
Phase 9 推荐分支 B'(双线修复,原 A/C 的 EAF 方案不适用):
- 9.1 应用层 jitter buffer(fill-threshold + drain)—— 解 B
- 9.2 开机 codec init 时序修复(ES7210 reset + ready 等待)—— 解 A
- 估时 1 天
ROADMAP 同步:Phase 7 矫正为 battery_psm(实际状态)、Phase 8 新增
诊断、Phase 9 占位待 Phase 8 决策、原"集成测试"挪到 Phase 10。
新增 .planning/STATE.md 记录 roadmap evolution。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 11:40:42 +08:00
4b3206dca3
docs(rtc-only): 对比报告 v2.1-v2.4 — 卡顿真凶定位 + 触顶诊断 + P4 升级路径
...
v2.1 §11.10 真凶定位:
- 通过 Baji+Kapi 同 Wi-Fi 对比日志, 证明卡顿不是网络问题
- Baji WiFi 缓冲 8/10 vs Kapi 16/16, 加上 LVGL/GIF 抢 PSRAM 总线
- 同 BSSID 同信号下 Baji reor=1790, Kapi reor=0~226 (8 倍差距)
- 新增 Phase 7.8/7.9 修复方向
v2.2 §11.11 GIF 4 方案评估:
- 方案 A (GIF EMBED 转 C 数组) ❌ 否决: 占 +2MB 爆 OTA 分区, PSRAM 带宽不变
- 方案 B (通话期暂停 GIF) ⭐ 强推荐: 20 行 / 0 内存代价 / reor 1800→500
- 方案 C (RGB565 帧序列) ❌ 否决: Flash 不够
- 方案 D (PNG 序列 + lv_anim) ⚠️ 复杂可考虑
- 新增 Phase 7.10/7.11
v2.3 §11.12 硬件触顶诊断:
- 用户最终需求(说话期 GIF + 触摸放大渐变 + RTC)超 ESP32-S3 极限
- 全并发 PSRAM 带宽需求 40MB/s, 接近物理极限 60MB/s 的 67%
- 给出 3 条路径: A 分模式策略 / B 极限优化 / C 换 ESP32-P4
- 新增 Phase 7.12 + Phase 8
v2.4 §11.13 ESP32-P4 完整需求容量评估:
- 几十套 GIF Flash 占用: 30 套 21MB / 100 套 70MB → P4 需 32/64MB
- PSRAM 32MB 按需 LRU 缓存, 同时驻留 10 套 GIF 仅占 5MB
- PPA 硬件 2D 加速: 触摸缩放从 30% CPU + 30MB/s PSRAM 降到零 CPU
- 外挂 ESP32-C6: WiFi 6 / BLE 5.3 (比 S3 WiFi 4 抗丢包更强)
- BOM 升级 ¥20→¥53/台 (+¥30), 开发周期 3-6 个月
- 结论: 长期产品强烈建议直接立项 P4 v2, S3 v1 作快速上市验证
- Phase 8 细化为 8.1-8.6 子任务
文档累计 1335 行, 完整覆盖"S3 优化探索 → 触顶诊断 → P4 升级"决策链。
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:51:34 +08:00
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
4b7b1949d4
perf(rtc-only): Phase 6 收尾 - 卡顿优化 + PowerSaveTimer 守卫 + 开机加速
...
代码改动:
- AudioLoop 加 vTaskDelay(1),让出 Core 1 idle task 防 WiFi/RTC 饥饿
- BackgroundTask 优先级 2 → 5,提升 Opus 解码实时性
- LVGL 刷新 5ms → 16ms (60Hz),CPU 占用降 60%
- GIF 定时器 20ms → 33ms (3 处),PSRAM 流量减半
- AI 字幕推送 100ms 节流,避免 LVGL 锁争抢
- EnterIdleHibernate 清空 audio_decode_queue_,防 standby_sound 残留误触发首帧
- PowerSaveTimer OnEnterSleepMode 加 device_state 守卫,拦截 dialog/connecting
期间关功放(修复欢迎语期间被静音 bug)
- 取消开机 ADC 阻塞采样,开机播报响应从 6 秒缩到 < 3 秒
新增规划:
- Phase 7 占位文档:电量保护 + PowerSaveTimer 重构 + 唤醒杂音根治 + RTC 抖动缓解
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 11:38:48 +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
f2be9922b6
feat(rtc-only): Phase 5 - RTC 字幕显示恢复(透明背景 + 2 行黑字 + 锁优化)
...
按 GSD 框架 .planning/milestones/digital_human_rtc/phases/phase_05_subtitle_restore/
规划完成 Phase 5 字幕显示恢复。
## 核心变更(main/dzbj/ai_chat_ui.c)
### 1. chat_container 重构
- 新增 static chat_container 变量(lv_obj 父容器)
- 尺寸 320×56(= 2 行字 + padding 4px*2)
- 位置 LV_ALIGN_BOTTOM_MID 距底 10px
- 完全透明背景(LV_OPA_TRANSP),无灰底
- 初始 HIDDEN,有内容时显示
### 2. chat_label 改造
- 黑色文本(用户反馈白字在浅色背景上不清晰)
- 尺寸 312×48 限制最多 2 行
- LV_LABEL_LONG_WRAP → LV_LABEL_LONG_DOT,超出 2 行自动 ... 截断
- font_puhui_20_4 中文字体不变
### 3. ai_chat_set_chat_message() 实现
原为空函数(PoC 期间 return),本 Phase 完整实现:
- 锁外去重:static last_content[256],相同内容直接返回
- lvgl_port_lock 200ms → 500ms(GIF 解码繁忙时给予更长等待)
- 内容空时隐藏容器,非空显示
- 成功更新后缓存 last_content
### 4. z-index 修复
bg_gif_demo_start() 后立即 lv_obj_move_foreground(chat_container)
否则 bg_img/gif_obj 后于 chat_container 创建会遮挡字幕
## 实测验证(用户协作)
60s 对话期间:
- ✅ AI 字幕完整推送 3 次(含 54 字符长字幕)
- ✅ LVGL 锁超时 14 次 → 0 次(锁外去重生效)
- ✅ 表情切换 + 字幕同步工作
- ✅ 长字幕自动 2 行截断
- ✅ 无 abort/重启
## 调用链(已对接 application.cc 现有逻辑,无需改协议层)
RTC 字幕 → display->SetChatMessage(role, msg)
→ AiChatDisplay::SetChatMessage
→ ai_chat_set_chat_message() ← 本 Phase 实现
## GSD 文档
- PLAN.md
- SUBTITLE_REPORT.md(含锁优化对比 + 布局规划 + 用户决策记录)
2026-05-13 13:35:41 +08:00
497c1b4654
feat(rtc-only): Phase 4 - 情绪标签 → 数字人 hiyori GIF 映射 + 切换接口
...
按 GSD 框架 .planning/milestones/digital_human_rtc/phases/phase_04_emotion_mapping/
规划完成 Phase 4 情绪映射 + 运行时切换。
## 核心变更
### bg_gif_demo 新增运行时切换接口
```c
esp_err_t bg_gif_demo_switch_gif(const char *new_gif_path);
```
实现要点:
- 先 heap_caps_free(g_gif_data) 释放旧 PSRAM,再加载新 GIF,单峰仅一份
- 内部 static last_gif_path 去重(相同路径直接返回 ESP_OK)
- 切换后立即 lv_timer_set_period(timer, 20) 防止 lv_gif_set_src 重建为默认 10ms
- LVGL 锁保护 200ms 超时
### 22 情绪 → 3 hiyori GIF 映射表
定义在 main/dzbj/ai_chat_ui.c USE_BG_GIF_POC 包裹内:
| GIF | 情绪标签 (个数) |
|-----|----------------|
| m06 (默认/积极) | neutral, happy, laughing, funny, loving, relaxed, delicious, kissy, confident, silly, blink, curious (12) |
| m07 (思考/疲倦) | sleepy, thinking, confused, embarrassed, dizzy (5) |
| m03 (负面/严肃) | sad, crying, angry, surprised, shocked (5) |
22 个标准情绪 100% 覆盖,未映射的情绪默认 fallback 到 m06。
### ai_chat_set_emotion 改造
PoC 模式下优先切换数字人大图(不再切隐藏的 emoji 200x89):
```c
#ifdef USE_BG_GIF_POC
if (bg_gif_demo_is_running()) {
const char *path = find_hiyori_gif(emotion);
bg_gif_demo_switch_gif(path);
return;
}
#endif
// 非 PoC 模式 fallback emoji 路径保留
```
## 调用链(已与现有 RTC 字幕解析对接,无需改 application.cc)
RTC 字幕 → application.cc:1419 display->SetEmotion(emo)
→ AiChatDisplay::SetEmotion (display/ai_chat_display.cc)
→ ai_chat_set_emotion (dzbj/ai_chat_ui.c)
→ bg_gif_demo_switch_gif (PoC 模式)
→ 数字人 hiyori GIF 切换
## 烧录验证(用户实测)
监控 60s 期间捕获情绪切换:
- neutral / happy → m06(已在播,去重)
- thinking → m07 切换成功 (590ms 延迟)
- confused → m07 去重跳过
- AI 回复结束 → 自动回到 neutral
- 无 abort / 重启
m06 ↔ m07 切换屏幕可视确认,m03 走相同代码路径无需重复测试。
## GSD 文档(同时提交)
- .planning/milestones/digital_human_rtc/phases/phase_04_emotion_mapping/PLAN.md
- .planning/milestones/digital_human_rtc/phases/phase_04_emotion_mapping/EMOTION_REPORT.md
2026-05-13 11:59:38 +08:00
7d1c7dc1f0
feat(rtc-only): Phase 3 - 数字人 GIF 资源准备(hiyori m03/m06/m07,209x360)
...
按 GSD 框架 .planning/milestones/digital_human_rtc/phases/phase_03_gif_resources/
规划完成 Phase 3 数字人表情 GIF 资源处理。
## 处理方式(与 PoC 阶段 hiyori_m05.gif 一致)
```bash
gifsicle --resize _x360 -O3 input.gif -o output.gif
```
- 高度 = LCD 360px,宽度按原比例自动算 → 209px
- 不裁剪(保持源 GIF 完整人物)
- 不加 --lossy / --colors(保留 256 色,画质优先)
- 只用 -O3 优化文件大小
## 处理结果
| GIF | 用途 | 源 | 处理后 | 节省 |
|-----|------|-----|--------|------|
| m03 | 负面/严肃 | 407×700 3.3MB | 209×360 1.15MB | 66% |
| m06 | 默认/积极 | 407×700 1.3MB | 209×360 0.44MB | 66% |
| m07 | 思考/疲倦 | 407×700 1.2MB | 209×360 0.40MB | 66% |
| 合计 | — | 5.7MB | 1.94MB | 66% |
## 决策过程(避免后续重复犯错)
Phase 3 初稿曾尝试裁剪到 240×320 + PIL 全帧 bbox 居中裁剪,
用户烧录后反馈"视觉感官不好"——角色被横向压扁(240×320 纵横比 0.75
vs 源 407×700 纵横比 0.583)。回归 PoC 等比例缩放方式后效果与 PoC 一致。
PoC 处理标准已写入用户级 feedback memory(feedback_hiyori_gif_processing.md),
后续 hiyori GIF 处理一律用本方式,除非用户主动要求修改。
## 显示效果(用户已目视确认)
LCD 360×360 居中显示 209×360 GIF:
- 垂直方向: 360 = 360,完全充满
- 横向: 209 < 360,左右各 75.5px 留边显示背景图
- 角色比例: 完整保留源 GIF 的 407:700 = 0.582 纵横比,人物细高自然
## 删除项
- spiffs_image/hiyori_m05.gif (2.3MB) 已删除 - 被 m06/m07/m03 替代
文件历史保留在 git,可通过 git show eb96130:spiffs_image/hiyori_m05.gif 恢复
## 默认表情切换
main/dzbj/ai_chat_ui.c:234:
- PoC: bg_gif_demo_start(..., "/spiflash/hiyori_m05.gif")
- Phase 3: bg_gif_demo_start(..., "/spiflash/hiyori_m06.gif")
## 烧录运行时验证
- 烧录后 0 次重启(连续监控 18 秒)
- BG_GIF: GIF 已加载到 PSRAM: /spiflash/hiyori_m06.gif (441.8 KB)
- AudioCodec: Audio codec started(首次冷启动直接成功)
- 用户目视确认显示效果良好
## GSD 文档(同时提交)
- .planning/milestones/digital_human_rtc/phases/phase_03_gif_resources/PLAN.md
- .planning/milestones/digital_human_rtc/phases/phase_03_gif_resources/GIF_REPORT.md
## SPIFFS 容量
新 SPIFFS 4.94MB 当前实际占用 ~2MB(40%),余量 ~2.94MB 充足。
2026-05-13 11:42:30 +08:00
ce7a3aad63
feat(rtc-only): Phase 2 - 16MB Flash 分区调整(OTA 5.5MB + SPIFFS 4.9MB)
...
按 GSD 框架 .planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/
规划完成 Phase 2 分区表调整,为 Phase 3 数字人 GIF 资源扩容铺路。
## 分区表变更
| 分区 | 旧 | 新 | 变化 |
|------|-----|-----|------|
| model | 0x10000 / 64KB | — 已移除 | -64KB |
| ota_0 | 0x20000 / 6.5MB | 0x10000 / 5.5MB | -1MB |
| ota_1 | 0x6A0000 / 6.5MB | 0x590000 / 5.5MB | -1MB |
| storage | 0xD20000 / 2.875MB | 0xB10000 / 4.9375MB | +2.0625MB |
合计:16MB(不变),SPIFFS 净扩容 2.0625MB
## 决策依据
- 当前 =n 固件 4.63MB,5.5MB ota 留 19% 成长 buffer
- SPIFFS 4.9MB 为 3 个 hiyori GIF + 背景图扩容(Phase 3 预算 ~3.9MB)
- 移除未使用的 64KB model 分区
- NVS 分区位置/大小不变,WiFi 凭据等数据完整保留
## 验收结果(详见 PARTITION_REPORT.md)
- =n 编译:✅ kapi.bin 4.63MB ≤ 5.5MB ota_0
- =y 双模式编译:链接通过但 6.05MB > 5.5MB ota(**预期降级**,
数字人 RTC 单一形态只用 =n 固件,Phase 3 资源精简后或可恢复)
- 烧录运行时验证:
✅ Running partition: ota_0
✅ NVS 数据完整保留(WiFi 凭据/设备配置)
✅ SPIFFS 自动挂载,hiyori_m05.gif 加载成功
✅ AI 对话模式启动,Codec 工作,WiFi 连接,RTC WebSocket 协议初始化
✅ free_heap=5.2MB(无 regression)
## GSD 文档(同时提交)
- .planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PLAN.md
- .planning/milestones/digital_human_rtc/phases/phase_02_partition_resize/PARTITION_REPORT.md
2026-05-13 11:00:35 +08:00
672506e7c7
feat(rtc-only): Phase 1 - 通过 CONFIG_BAJI_BADGE_MODE 屏蔽电子吧唧模式
...
按 GSD 框架 .planning/milestones/digital_human_rtc/ 规划完成 Phase 1。
源代码全部保留,通过 Kconfig 开关 + CMakeLists 条件编译 + #ifdef 调用点保护
实现"吧唧模式不进固件但代码可恢复"。
## 核心变更
### Kconfig 开关(默认关闭)
- 新增 CONFIG_BAJI_BADGE_MODE(main/Kconfig.projbuild)
- sdkconfig.defaults 默认 =n
- =y 时恢复双模式(电子吧唧 + AI 对话)
- =n 时仅 AI 数字人 RTC 模式
### CMakeLists 剥离(剥离式不重写)
- 9 个 dzbj/ 吧唧专属 + 9 个 ui/screens/ 吧唧 UI 进入 if(CONFIG_BAJI_BADGE_MODE) 条件块
- 公共保留: dzbj/lcd.c, ai_chat_ui.c, sprite_demo.c, dual_gif_demo.c,
bg_gif_demo.c, pages_pwm.c, dzbj_init.c, fatfs.c
- 修正 PLAN 漏判:dzbj_init/fatfs 公共化(AI 模式调用 dzbj_hw_display_init/DecodeImg)
### 调用点 #ifdef 保护
- application.cc: L20 include, L63-66 background_task, L536 device_mode 分支
- movecall_moji_esp32s3.cc: dzbj headers, init_spiffs_image_list extern,
dzbj_boot_click_handler extern, device_mode_is_badge 分支, InitializeBadgeMode,
InitializeBadgeModeButtons, mode_switch_combo 注册, device_mode_in_switch_suppress
- 保留公共 extern: ai_chat_screen_init, ai_chat_resume_animation, pwm_init
### 整体文件级 #ifdef 包裹
- dzbj/dzbj_button.c/h
- dzbj/sleep_mgr.c
- sleep_mgr/include/sleep_mgr.h
### 6 个文件显式 #include "sdkconfig.h"
- ESP-IDF 不会 force-include,必须手动 include 才能拿到 CONFIG_* 宏
## G7 验收双向编译
- =n 模式 build: ✅ EXIT=0(数字人 RTC 单一形态)
- =y 模式 build: ✅ EXIT=0(双模式恢复可用)
## 固件大小变化
| 段 | =n | =y | 节省 |
|----|-----|------|------|
| .text | 2.03 MB | 2.06 MB | 27 KB |
| .rodata | 2.48 MB | 3.87 MB | 1.39 MB |
| Total | 4.63 MB | 6.05 MB | 1.45 MB |
## GSD 文档(同时提交)
- .planning/milestones/digital_human_rtc/MILESTONE.md
- .planning/milestones/digital_human_rtc/ROADMAP.md
- .planning/milestones/digital_human_rtc/INTEL.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/PLAN.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/SIZE_REPORT.md
- .planning/milestones/digital_human_rtc/phases/phase_01_kconfig_isolation/BADGE_MODE_ISOLATION_MAP.md
- 编译大小原始数据: size_*.txt
## 已知事项
- =n 固件 4.63 MB 仍 > 4 MB 目标,Phase 2 调整分区 + Phase 3 物理移除图片资源解决
- main/dzbj/ 下所有源文件完整保留,无任何物理删除
2026-05-13 10:22:48 +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
6208930001
chore: 更新插件指南/sdkconfig/IDF串口配置 + 从仓库移除 .DS_Store
...
变更清单:
1、Claude Code 插件指南:新增 GSD 执行框架章节 + 第三方 Skills(think/health)说明
+ 新电脑环境恢复指南完善(增加 GSD 安装步骤、第三方 Skills 数量更新为 7 个)
2、sdkconfig:ESP-IDF SoC 配置项更新(GDMA/LCDCAM/CPU watchpoint 格式调整)
3、.vscode/settings.json:IDF 串口号从 usbmodem834101 更新为 usbmodem834401
4、从 Git 仓库移除 3 个 .DS_Store(.gitignore 已有规则但早期被跟踪)
- .DS_Store
- main/.DS_Store
- main/ui/.DS_Store
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 14:10:36 +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
b35d86f84c
docs: 更新 Claude Code 插件指南 + 新增开发参考文档
...
Claude Code插件高效运用指南.md:
1、补充遗漏的内置 Skills(schedule/update-config/keybindings-help)
2、新增第三方 Skills 记录(find-skills/tmux/summarize/tavily-research/embedded-systems)
3、新增第八章:新电脑环境恢复指南(含 ESP-IDF v5.4.2 安装步骤)
4、新增步骤 3.1:第三方 Skills 安装命令
新增文档:
5、Claude Code 十个最值得装的 Skills copy.md — 微信文章内容存档
6、资深嵌入式工程师开发思维.md — 嵌入式开发核心思维与注意事项
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 10:09:08 +08:00
0bdf7be875
feat: 应援灯防撕裂优化 - DMA直接填充GRAM + LVGL flush拦截 + PWM黑屏遮蔽
...
应援灯颜色切换从 LVGL 渲染改为直接 DMA 填充 GRAM,彻底消除 LVGL 刷新竞争:
lcd.c/lcd.h:
- 新增 lcd_fill_color_with_buf() 直接 DMA 分条填充全屏纯色
- 新增 TEON(0x35) 启用 TE 内部同步信号
- 新增 lcd_read_scanline()/lcd_wait_vsync_timeout() VSYNC 读取接口
(实测 QSPI 模式下 TESLRD 始终返回 0xFFFF,软件 VSYNC 不可用)
ui_ScreenSet.c:
- LVGL flush 回调拦截:进入应援灯时替换为空操作,退出时恢复
解决 LVGL 周期刷新覆盖 DMA 颜色导致红色方块残留的问题
- DMA 缓冲区生命周期管理:进入时分配,退出时释放
- 颜色切换 PWM=0 黑屏遮蔽:DMA 期间完全熄灭背光,撕裂不可见
- 滑块交互优化:拖动期间锁定其他按钮 + PWM 50ms 节流
- 手动滑动检测替代 LVGL 手势(layer_top 上手势不可靠)
.gitignore: 排除 docs/*.pdf 文档文件
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 15:18:41 +08:00
99d7e910f1
补充提交:无关紧要的文件修改,不用理会
2026-03-27 10:59:33 +08:00
0735d45e52
feat: 从按键版迁移APP传图、设备间图片分享/接收、组合键模式切换功能
...
## 功能迁移清单(从 Dzbj_ESP32_S3_Key → Baji_Rtc_Toy)
### 1. 设备间BLE图片传输(GATT Client + 协议)
- 新增 ble_transfer.c/h:发送方 GATT Client 扫描→连接→MTU协商→分包写入
- 接收方复用现有 GATT Server(IMAGE_WRITE 0x0B01),协议完全兼容
- 发送完成/失败自动跳转 Img 界面并关闭蓝牙
### 2. APP传图显示 Update 界面
- 新增 ui_ScreenUpdate.c/h:更新进度界面(Gengxin背景 + Update_GIF动画)
- dzbj_ble.c WRITE_EVT 中通过 ble_transfer_is_receiving() 区分 APP传图 vs 设备间传输
- APP传图 → ScreenUpdate,设备间传输 → ScreenReceiving
### 3. KEY2 按键功能入口(iot_button 单击/双击/长按)
- KEY2 单击:开蓝牙 → Peiwang 配对界面(APP传图)
- KEY2 双击:接收模式 → ScreenImageReception(等待配对)
- KEY2 长按:发送模式 → ScreenImageShar(等待配对)
- 按键参数与按键版对齐:long_press_time=1200ms, short_press_time=300ms
### 4. BOOT+KEY2 组合键模式切换(替代 BOOT 长按3秒)
- BOOT 2秒长按 + KEY2 同时按下 → 触发模式切换
- 消除单键长按的误触发问题
- AI模式和吧唧模式均注册组合键
### 5. 按键上下文状态机
- btn_context_t 枚举:HOME/IMG/SET/PEIWANG/IMAGE_SHAR/IMAGE_RECEPTION/SHARING/RECEIVING/UPDATE
- 所有界面切换点(手势/按键/BLE自动跳转)同步设置 context
- BOOT 单击按 context 分发:Home无操作、Img/Set返回Home、配对退出蓝牙、传输等待取消
### 6. 新增 UI 界面(6个Screen + 7张图片)
- ScreenPeiwang:蓝牙配对等待
- ScreenUpdate:APP传图更新中
- ScreenImageShar:发送方等待配对
- ScreenImageReception:接收方等待配对
- ScreenSharing:发送方传输中
- ScreenReceiving:接收方接收中
### 7. 其他适配
- BLE 广播改为按需启动(dzbj_ble_start/stop/is_active)
- sleep_mgr 移除 KEY2 唤醒(仅 BOOT 唤醒屏幕)
- device_mode 新增模式切换按键抑制(防止重启后立即触发)
- battery_ui 电池指示器组件
- sdkconfig 启用 BLE GATTC 支持
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 10:55:17 +08:00
32c3dc69bc
fix: 滑动切换图片时自动跳过解码失败的无效图片
...
1、update_ui_ImgBle 返回类型 void → bool,解码成功返回 true,失败返回 false;
2、左滑/右滑手势回调添加 for 循环,解码失败自动跳到下一张(最多尝试 10 张防死循环);
3、更新最新设备运行日志;
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 18:22:53 +08:00
4e2f6906f9
feat: 启用 BLE 5.0 2M PHY 图传加速 + 移除未使用的 BluFi 组件 + BLE 断连内存泄漏修复
...
1、dzbj_ble.c 新增 BLE 5.0 2M PHY 请求(连接时自动协商,不支持则回退 1M);
2、dzbj_ble.c 新增 PHY 更新事件日志(tx_phy/rx_phy: 1=1M, 2=2M, 3=Coded);
3、dzbj_ble.c 断连时清理未完成的图片传输状态,释放 img_data/filepath/file_img 防止内存泄漏;
4、移除未使用的 BluFi 组件依赖(Kconfig select、编译检查、sdkconfig),解除与 BLE 5.0 的兼容冲突;
5、sdkconfig.defaults 及生产环境配置统一启用 BLE 5.0 + 保留 BLE 4.2 legacy advertising 兼容;
6、新增 BLE 图片传输问题分析与优化建议文档(含 UniApp vs Flutter 对比分析,供 APP 开发者参考);
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 17:12:35 +08:00
af58123d66
1、更新Claude插件高效运用的使用方法;
...
2、更新电子吧唧AI触屏版 → 按键版迁移总结
2026-03-23 10:30:44 +08:00
919bf8f28f
feat: GIF动画表情系统 + 情绪映射增强 + HTTPS音频中止修复
...
一、新增功能:
1、新增8种GIF动画表情(200x89) + 3种叠加图标(45x45),实现22种情绪标签到GIF的映射表;
2、新增30+组英文近义词情绪fallback映射(如worried→sad),防止AI使用非标准标签时GIF无法切换;
3、新增HTTPS中止后诊断日志,自动追踪前20帧音频处理流程便于定位无声问题;
二、Bug修复:
4、修复HTTPS播放中止后RTC音频解码参数未恢复(16000/60→8000/20),通过background_task_串行化恢复;
5、修复AbortHttpsPlayback解码器竞态崩溃,将重置/恢复/DMA flush全部串行化执行;
6、修复LVGL gifdec不支持无全局颜色表GIF的问题,支持仅使用局部颜色表的压缩GIF;
7、修复GIF透明区域显示黑色方块,canvas初始alpha改为0x00;
8、修复lv_gif定时器gif对象为NULL时的空指针崩溃;
三、优化:
9、情绪标签从等待is_final改为第一条字幕即时触发GIF切换,新增去重和回复结束自动恢复neutral;
10、对话状态表情映射优化:THINKING→thinking、ANSWERING→happy、INTERRUPTED→surprised;
11、CPU核心绑定:LVGL任务Core0,音频循环Core1,避免GIF解码与音频争抢;
12、中文情绪词映射扩展,新增担心/心疼/着急等映射;
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:28:14 +08:00
da098bf482
1、新增了在日志打印中接收字幕详细信息的代码
2026-03-17 09:45:29 +08:00
e2ec9f36aa
1、启用LVGL GIF解码器(CONFIG_LV_USE_GIF=y),支持吧唧模式GIF图片BLE传输和播放;
...
2、LVGL内存管理切换为系统malloc(CONFIG_LV_MEM_CUSTOM=y),使gifdec大块分配走PSRAM避免内部堆不足;
3、pages.h stub头文件补充pages_cleanup_gif()声明,修复ui_ScreenImg.c编译隐式声明错误;
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 17:36:18 +08:00
23613e1cd3
1、新增obtain_music Function Calling音乐播放功能,4处协议分支均支持URL直播和音乐API两种HTTPS方式;
...
2、Kconfig新增MUSIC_API_URL音乐播放API地址配置;
3、重构SendStoryRequest和SendMusicRequest为HttpsApiPlayback通用方法,消除故事/音乐播放~440行重复代码;
4、修正4处obtain_story注释和日志:WebSocket描述改为HTTPS API(与实际实现一致);
2026-03-05 15:44:47 +08:00
ccea0c681c
feat: HTTPS故事播放 + RTC/HTTPS双向音频切换状态机 + 协议层优化
...
1、新增HTTPS故事播放功能:SendStoryRequest通过蓝牙MAC请求故事API,支持intro+body两段式无缝播放,替换原WebSocket故事请求方式;
2、新增HttpsPlaybackFromUrl通用HTTPS音频下载播放方法,支持JSON格式Opus帧流式解码播放;
3、新增RTC↔HTTPS双向音频切换三标志位状态机(opus_playback_active_/https_playback_active_/https_playback_abort_),HTTPS播放期间静默丢弃RTC PCM包,OnAudioOutput捕获is_opus_frame防止残留Opus帧杂音;
4、新增AbortHttpsPlayback中止方法,使用独立高优先级任务(priority=10)执行DMA flush;AbortSpeaking也新增DMA缓冲区flush确保扬声器立即静音;
5、协议层新增OnBotMessage回调,非字幕Bot下行消息立即中止HTTPS播放;volc_rtc_protocol移除is_binary依赖改为直接前缀检测,新增info前缀识别,subv字幕排除on_bot_message_由subtitle handler单独处理;
6、subtitle字幕USER/AI区分从CONFIG_VOLC_DEVICE_NAME比较改为bot_前缀判断,用户说话时立即中止HTTPS播放;
7、Kconfig新增STORY_API_URL故事播放API地址配置;
8、设备注册RTC服务时,设备名称从Wi-Fi MAC地址改为使用蓝牙MAC地址
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:45:52 +08:00
1e7ba0763a
1、更新了postman参数、约束和语音请求讲故事的Function Call参数;
...
2、字幕增加了情绪标签,并且emoji表情跟随情绪和设备状态而更新;
2026-03-02 17:27:03 +08:00
04d26d7cee
1、本次新增了Function Calling的讲故事功能,可以语音获取小故事
2026-03-02 15:34:41 +08:00
7082d2a818
补充提交postman请求参数
2026-03-02 15:12:28 +08:00
98e40ac163
feat: 火山RTC字幕文本实时显示 + 字幕日志精简
...
1. DataCallback 新增 subv(字幕)二进制消息前缀识别,字幕数据正确解析并转发到应用层
2. OnIncomingJson 处理 type:"subtitle",通过 userId 区分用户语音识别(STT)和 AI 回复文本
3. 字幕日志简化:subv 消息仅打印"接收下行二进制消息(字幕)",不展开 JSON 内容
4. 新增postman请求的参数
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 15:11:34 +08:00
0a6b35d979
1、新增提交postman请求的Open_API参数(稳定无报错版本)
2026-03-02 10:12:59 +08:00
58c33e3cb4
feat: AI对话模式emoji表情系统 + 中文字体 + 分区优化
...
1. 新增AI对话LVGL界面(ai_chat_ui),支持emoji图片 + 状态文本 + 聊天消息
2. 新增7个emoji表情资源(64×64 PNG C数组):neutral/happy/sad/angry/crying/funny/laughing
3. 新增阿里巴巴普惠体20px 4bpp中文字体(GB2312字符集)
4. 利用火山RTC会话状态(VOLC_MSG_CONV_STATUS)驱动emoji切换:
- LISTENING→happy, THINKING→neutral, ANSWERING→laughing
- INTERRUPTED→funny, ANSWER_FINISH→happy
5. 设备状态emoji映射:Listening→happy, Speaking→laughing, Dialog→happy
6. 配网模式显示happy emoji
7. 分区优化:model 3MB→64KB,OTA 5MB→6.5MB
8. 编译优化:-Og→-Os,移除SimSun CJK字体
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:14:19 +08:00