47 lines
2.1 KiB
Markdown
47 lines
2.1 KiB
Markdown
# 雪碧图 VTT 拖动预览
|
||
|
||
## 目标
|
||
|
||
将进度条拖动预览主链路改为服务端雪碧图 + WebVTT 局部裁剪,原生取帧只作为降级:
|
||
|
||
1. `Episode` 与 `PlayTicket` 解析 `thumbnailsUrl`。
|
||
2. VTT 只拉取/解析一次,内存缓存 10 分钟。
|
||
3. cue 使用起止时间 + 相对 sprite 文件名 + `xywh`,按 position 二分选择。
|
||
4. sprite 图最多缓存 2 张 `ui.Image`,拖动帧只绘制 sourceRect。
|
||
5. 无 VTT、空轴或图片失败时回退现有 `PlaybackThumbnailService`,再回退封面。
|
||
|
||
## 性能红线
|
||
|
||
- 拖动帧禁止网络请求与图片解码,只允许 cue 二分查找和 `RawImage.sourceRect` 绘制。
|
||
- VTT 每个 URL 只解析一次;sprite 解码不在 build/build paint 中执行。
|
||
- sprite ui.Image LRU 上限 2 张,页面 dispose 清空。
|
||
- 解码 sprite 最长边超过 2048px 时按比例缩小后常驻。
|
||
- 签名 `thumbnailsUrl` 不写入任何持久化缓存。
|
||
|
||
## 实施
|
||
|
||
- 新增 `SpriteThumbnailAxisService`:
|
||
- Dio 拉取 VTT,403 清缓存后重试一次;
|
||
- 解析和选 cue 为纯函数,解析失败返回空轴;
|
||
- 播放器就绪时预取当前 cue 及相邻 sprite;
|
||
- LRU2 sprite 缓存和 10 分钟 VTT 缓存。
|
||
- `PlayerPage` 持有页面级服务,按当前选中集预取,dispose 时清空。
|
||
- `ScrubPreviewCard` 优先读取已缓存 sprite frame,显示 `RawImage` 裁剪;
|
||
VTT 未就绪时暂显封面,轴为空/不可用后启动本地取帧,全部失败保留封面。
|
||
- 首页 feed 和全屏播放器都把 `thumbnailsUrl` 传到预览卡片。
|
||
- 不新增 pub 依赖、不改后端契约。
|
||
|
||
## 测试
|
||
|
||
- VTT 解析:时间、xywh、多 sprite 文件。
|
||
- cue 选择:命中、越界最近邻。
|
||
- sprite LRU 最多 2 张。
|
||
- 回退状态判定。
|
||
- Widget:sprite 裁剪且不触发本地取帧;无 URL 回退本地;全部失败显示封面。
|
||
- 门禁:`dart analyze lib test`、`flutter test --no-pub`。
|
||
|
||
## 风险
|
||
|
||
- 真实网络 VTT/sprite 可访问性和签名过期由 PM 真机验收。
|
||
- 本次不启动服务、不操作真机、不修改 Web/FruitServer。
|