Files
Mdeical_Sur_Report/过往经验/实现方案-2026-04-16-20-46-50.md

4.1 KiB
Raw Blame History

实现方案 — 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 静默吞掉。

实际发生的过程:

  1. 用户上传视频 → 此时 videos 数组中的 urlblob:http://...(短字符串),数据量很小,保存成功
  2. 系统开始自动抽帧,生成巨大的 Base64 dataUrl 数组;
  3. 调用 saveDraftToStorage() 尝试保存时,localStorage.setItem 触发超限报错;
  4. 异常被 catch 忽略,draft 没有被更新(或更新失败);
  5. 当用户离开页面再返回时localStorage 中读到的 draft 仍然停留在"仅有视频、没有关键帧"的状态。

这就是为什么:编辑器内容保留了,视频保留了,但关键帧全部消失

修改方向

方向一:压缩关键帧分辨率与质量(快速修复,推荐优先执行)

关键帧只是用于插入报告的缩略图,通常不需要 4K 原画质。可以:

  1. 设定最大宽度(如 800px等比缩放 Canvas
  2. 将 JPEG 导出质量从 0.9 降到 0.5 ~ 0.6
  3. 这样单张图片体积可从 500KB 压缩到 30KB~80KB十几张关键帧总计不到 1MB远低于 5MB 限制。

修改点:

  • captureFrame()(手动截图)
  • autoCaptureFrames()(自动抽帧)

方向二:增加存储超限的可见性

storage.ts 中不再静默吞掉异常,而是至少输出 console.error,甚至可以在 UI 层捕获后提示用户: "报告数据过大,请降低视频截图质量或删除部分图片。"

方向三:迁移到 IndexedDB长期根治

localStorage 的 5MB 上限对于包含大量 Base64 图片的医疗报告系统来说迟早会不够用。长期方案是:

  • 引入 localforageidb-keyval 等轻量库;
  • storage.ts 改造为基于 IndexedDB 的异步存储方案(容量可达数百 MB

注意: 方向三涉及全项目的 storage.get/set 调用点从同步改为异步,改动面较大,适合作为后续迭代项目。

建议的实施方案

本次优先执行方向一 + 方向二,以最快速度解决关键帧丢失问题,并让用户感知到存储异常:

  1. captureFrameautoCaptureFrames 中增加 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);
    
  2. storage.ts 中增加超限日志:

    } catch (e) {
      console.error('Storage save failed (possibly quota exceeded):', e);
    }
    

风险点

风险 级别 应对措施
压缩后图片清晰度下降 800px 宽度 + 0.6 质量对于报告插入足够清晰
仍有个别超长视频压缩后接近 5MB 极低 配合方向二的日志提示,便于后续继续优化

回滚策略

仅调整 Canvas 缩放参数和 JPEG 质量,不涉及数据结构和接口变更。如有异常可直接 revert。


⚠️ 请审核以上方案,确认无误后回复「确认」或提出修改意见,我将进入测试方案编写阶段。