4.1 KiB
4.1 KiB
实现方案 — 2026-04-16-20-46-50
根因分析
1. LocalStorage 容量超限(QuotaExceededError)
浏览器对单个域名的 localStorage 通常有 5MB 的严格容量限制。
当前代码在抽帧时使用了视频的原始分辨率:
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
const dataUrl = canvas.toDataURL('image/jpeg', 0.9);
如果上传的是 1080p 甚至 4K 视频:
- 单张 0.9 质量 JPEG Base64 图片可能达到 300KB ~ 1MB;
- 自动提取 12 张关键帧 + 手动截图若干张,总数据量可能达到 5MB ~ 10MB;
- 直接超过
localStorage的 5MB 上限。
2. 静默失败
src/utils/storage.ts 中的 set 方法:
set<T>(key: string, value: T): void {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch {
// ignore quota exceeded
}
}
当数据量超过 5MB 时,localStorage.setItem 抛出 QuotaExceededError,但被 catch 静默吞掉。
实际发生的过程:
- 用户上传视频 → 此时
videos数组中的url是blob:http://...(短字符串),数据量很小,保存成功; - 系统开始自动抽帧,生成巨大的 Base64
dataUrl数组; - 调用
saveDraftToStorage()尝试保存时,localStorage.setItem触发超限报错; - 异常被
catch忽略,draft 没有被更新(或更新失败); - 当用户离开页面再返回时,localStorage 中读到的 draft 仍然停留在"仅有视频、没有关键帧"的状态。
这就是为什么:编辑器内容保留了,视频保留了,但关键帧全部消失。
修改方向
方向一:压缩关键帧分辨率与质量(快速修复,推荐优先执行)
关键帧只是用于插入报告的缩略图,通常不需要 4K 原画质。可以:
- 设定最大宽度(如 800px),等比缩放 Canvas;
- 将 JPEG 导出质量从
0.9降到0.5 ~ 0.6; - 这样单张图片体积可从 500KB 压缩到 30KB~80KB,十几张关键帧总计不到 1MB,远低于 5MB 限制。
修改点:
captureFrame()(手动截图)autoCaptureFrames()(自动抽帧)
方向二:增加存储超限的可见性
在 storage.ts 中不再静默吞掉异常,而是至少输出 console.error,甚至可以在 UI 层捕获后提示用户:
"报告数据过大,请降低视频截图质量或删除部分图片。"
方向三:迁移到 IndexedDB(长期根治)
localStorage 的 5MB 上限对于包含大量 Base64 图片的医疗报告系统来说迟早会不够用。长期方案是:
- 引入
localforage或idb-keyval等轻量库; - 将
storage.ts改造为基于 IndexedDB 的异步存储方案(容量可达数百 MB)。
注意: 方向三涉及全项目的 storage.get/set 调用点从同步改为异步,改动面较大,适合作为后续迭代项目。
建议的实施方案
本次优先执行方向一 + 方向二,以最快速度解决关键帧丢失问题,并让用户感知到存储异常:
-
在
captureFrame和autoCaptureFrames中增加 Canvas 等比缩放逻辑:const MAX_WIDTH = 800; const scale = Math.min(1, MAX_WIDTH / video.videoWidth); canvas.width = video.videoWidth * scale; canvas.height = video.videoHeight * scale; ctx?.drawImage(video, 0, 0, canvas.width, canvas.height); const dataUrl = canvas.toDataURL('image/jpeg', 0.6); -
在
storage.ts中增加超限日志:} catch (e) { console.error('Storage save failed (possibly quota exceeded):', e); }
风险点
| 风险 | 级别 | 应对措施 |
|---|---|---|
| 压缩后图片清晰度下降 | 低 | 800px 宽度 + 0.6 质量对于报告插入足够清晰 |
| 仍有个别超长视频压缩后接近 5MB | 极低 | 配合方向二的日志提示,便于后续继续优化 |
回滚策略
仅调整 Canvas 缩放参数和 JPEG 质量,不涉及数据结构和接口变更。如有异常可直接 revert。
⚠️ 请审核以上方案,确认无误后回复「确认」或提出修改意见,我将进入测试方案编写阶段。