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 张图传图片和容量验证过程。
This commit is contained in:
Rdzleo 2026-06-02 15:39:10 +08:00
parent 6b166f4463
commit 55da5297ee
4 changed files with 1734 additions and 922 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,273 @@
# 电子吧唧 GIF 图传转 EAF 方案分析
## 背景
当前 Baji_Rtc_Toy 双模式固件包含两条显示链路:
- RTC 数字人模式:使用 EAF/esp_emote_gfx 播放 `/spiflash/hiyori-assets.bin`,播放流畅。
- 电子吧唧模式:使用 LVGL/SquareLine 显示图片APP 图传支持 JPG/GIF。
当前 EAF 数字人资源来自:
```text
/Users/rdzleo/Desktop/Baji_Rtc_Toy/spiffs_image/hiyori-assets.bin
```
烧录后设备运行时路径为:
```text
/spiflash/hiyori-assets.bin
```
该文件由乐鑫 ESP Emote GFX Packer NEXT 将 GIF/动画资源预转换后生成,再打包进 SPIFFS 的 `storage` 分区。
## 当前 GIF 图传现状
当前电子吧唧支持 GIF 图传:
- `CONFIG_LV_USE_GIF=y`
- BLE 接收到 GIF 后可走 `ble_image_navigate_with_data()`
- 设备端使用 `gifdec` 解码 GIF
- 播放路径仍属于 LVGL 图片页
GIF 在 ESP32 上播放的资源开销较大,原因包括:
- GIF 需要运行时 LZW 解码。
- 每帧需要处理 disposal、透明色、调色板。
- 帧数据需要转换为 LCD 可刷新的 RGB565 缓冲。
- 高分辨率、高帧率、长时长 GIF 会占用较多 PSRAM、CPU 和显示刷新时间。
因此 GIF 可以作为兼容路径保留,但不适合作为大量动态图片的主方案。
## EAF 方案原理
EAF 的核心优势是:把复杂动画处理提前放到转换阶段,设备端只负责播放预处理后的资源。
典型流程:
```text
GIF / Lottie / 动画源
ESP Emote GFX Packer NEXT 转换
EAF / binary asset pack
写入 SPIFFS / 分区 / 文件系统
ESP32 使用 esp_emote_gfx 播放
```
当前 RTC 数字人就是这个路线,因此比直接播放 GIF 更流畅。
## 方案一:继续支持 GIF 图传并做 APP 端限制
这是最短期、改动最少的方案。
建议 APP 端限制:
- 分辨率不超过 360x360。
- 帧率控制在 10-15 FPS。
- 时长控制在 2-3 秒。
- 文件大小建议小于 500 KB。
- 尽量减少透明帧和复杂 disposal。
优点:
- 设备端改动少。
- APP 端开发成本低。
- 现有 BLE 图传链路可以继续使用。
缺点:
- ESP32 仍然需要运行时解码 GIF。
- 复杂 GIF 仍可能导致卡顿、内存压力或播放不稳定。
- 用户体验受 GIF 文件质量影响很大。
适用场景:
- 作为短期兼容方案。
- 允许用户传少量、短时、低复杂度 GIF。
## 方案二:服务器端转换 GIF 为 EAF
这是推荐的中期方案。
流程:
```text
手机 APP 选择 GIF
上传服务器
服务器调用或复刻 EAF Packer 转换为 .bin
APP 下载转换后的 .bin
APP 通过 BLE 发送 .bin 到设备
设备保存到 /spiflash/user_emote_xxx.bin
设备使用 EAF 播放器播放
```
优点:
- Android/iOS 不需要各自实现复杂转换器。
- EAF 转换逻辑集中在服务器,后续升级维护简单。
- 设备端播放更流畅,资源压力明显低于 GIF。
- 可以在服务器端统一压缩、裁剪、限帧、质检。
缺点:
- 需要服务器能力。
- APP 需要上传/下载流程。
- 用户离线时无法转换新 GIF。
- 设备端需要新增“用户 EAF bin 播放”路径。
适用场景:
- 产品化推荐方案。
- 后续需要支持大量用户自定义动态图。
- 希望设备端播放稳定、流畅。
## 方案三Android/iOS APP 内置 EAF 转换器
这是长期可探索方案,但不建议作为第一阶段目标。
APP 端需要处理:
- GIF 解码。
- 帧时间轴。
- disposal 规则。
- 透明色和调色板。
- 缩放、裁剪、帧率限制。
- RGB565 或 EAF 所需像素格式转换。
- EAF/bin 打包格式。
- 压缩策略。
- 与设备端 esp_emote_gfx 播放器兼容。
可行方式:
- 如果乐鑫 Packer 的转换逻辑可独立复用,可考虑移植为 JS/WASM再嵌入 Android/iOS。
- 如果只有设备端 player而转换器源码不可直接复用则从零实现成本较高。
优点:
- 用户不依赖服务器。
- APP 端可离线转换。
- 转换完成后直接 BLE 下发。
缺点:
- Android/iOS 双端开发成本高。
- 转换格式兼容性需要长期维护。
- 调试成本高,容易出现设备端无法播放、帧错乱、颜色异常等问题。
适用场景:
- 后期产品成熟后再评估。
- 有明确离线转换需求。
- 能拿到或稳定复用 EAF Packer 转换逻辑。
## 设备端需要新增的能力
如果要让 APP 传来的资源以 EAF 播放,设备端不能只接收 `.bin` 文件,还需要新增播放路径。
建议新增能力:
1. BLE 图传协议区分资源类型:
- JPG
- GIF
- EAF bin
2. EAF bin 保存路径:
```text
/spiflash/user_emote_xxx.bin
```
3. 电子吧唧模式支持识别 `.bin` 动画资源。
4. 播放 EAF 前处理显示管线:
- 当前电子吧唧 UI 使用 LVGL。
- EAF 使用 esp_emote_gfx。
- 两者不能同时抢同一个 LCD flush。
5. 可选策略:
- 进入 EAF 动画播放页时暂停 LVGL 刷新或退出当前 LVGL 图片页。
- EAF 播放完成后恢复 LVGL UI。
- 或者为电子吧唧动态图设计独立 EAF 播放模式,避免热切换复杂度。
## 存储建议
当前资源都在 SPIFFS
```text
/spiflash/hiyori-assets.bin
/spiflash/Background_360x360.jpg
/spiflash/default.jpg
/spiflash/02.jpg
/spiflash/face_xxx.jpg
```
当前已取消 OTA并扩大 `storage` 分区。短期内可以继续使用片内 SPI Flash。
后续如果 EAF 用户资源较多,可考虑:
- 继续优化分区,将更多空间给 storage。
- 换更大容量主 SPI Flash。
- 外挂独立 NOR Flash并挂载为 `/extflash`
优先级建议:
```text
扩大当前 storage 分区
更换更大容量主 Flash
外挂独立 NOR Flash
```
外挂 NOR Flash 可行,但会引入新的硬件和驱动适配工作,不建议在第一阶段引入。
## 推荐实施顺序
### 第一阶段:保留 GIF限制 GIF 规格
- APP 限制 GIF 分辨率、帧率、时长和大小。
- 设备端继续使用现有 GIF 播放路径。
- 用于短期兼容和快速验证用户需求。
### 第二阶段:设备端支持用户 EAF bin 播放
- BLE 协议支持 `.bin` 类型。
- 设备保存用户 EAF 到 `/spiflash`
- 增加电子吧唧 EAF 播放入口。
- 明确 LVGL 与 EAF 的显示管线切换策略。
### 第三阶段:服务器端 GIF 转 EAF
- 服务器端实现 GIF 到 EAF/bin 转换。
- APP 上传 GIF下载 EAF bin。
- APP 将 EAF bin 通过 BLE 发送给设备。
### 第四阶段:评估 APP 端离线转换
- 调研 EAF Packer 转换逻辑是否可复用。
- 如果可复用,优先考虑 JS/WASM + 双端 WebView/Native Bridge。
- 如果不可复用,不建议双端从零实现。
## 最终建议
不要一开始就在 Android/iOS 双端实现完整 EAF 转换器。
建议路线:
```text
短期:限制 GIF 参数,保留现有 GIF 图传
中期:设备端支持用户 EAF bin 播放
中期:服务器端完成 GIF → EAF bin 转换
长期:再评估 APP 端离线 EAF 转换
```
这样可以把最复杂的转换逻辑放在服务器,保证设备端播放流畅,同时降低 Android/iOS 双端开发和维护成本。

View File

@ -31,7 +31,7 @@ uint8_t *app_img_data = 0;
esp_jpeg_image_output_t outdata; esp_jpeg_image_output_t outdata;
lv_img_dsc_t image; lv_img_dsc_t image;
#define MAX_IMAGE_FILES 10 #define MAX_IMAGE_FILES 100
#define MAX_FILENAME_LEN 32 #define MAX_FILENAME_LEN 32
static char spiffs_image_files[MAX_IMAGE_FILES][MAX_FILENAME_LEN]; static char spiffs_image_files[MAX_IMAGE_FILES][MAX_FILENAME_LEN];
static int spiffs_image_count = 0; static int spiffs_image_count = 0;

View File

@ -2,5 +2,5 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000, nvs, data, nvs, 0x9000, 0x4000,
phy_init, data, phy, 0xf000, 0x1000, phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x900000, factory, app, factory, 0x10000, 0x700000,
storage, data, spiffs, 0x910000, 0x6F0000, storage, data, spiffs, 0x710000, 0x8F0000,

1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x4000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 0x900000, factory, app, factory, 0x10000, 0x700000,
6 storage, data, spiffs, 0x910000, 0x6F0000, storage, data, spiffs, 0x710000, 0x8F0000,