|
| 1 | +# 画面要点 OCR 价值提升 + 会话/笔记序号补位设计 |
| 2 | + |
| 3 | +> 日期:2026-08-21 |
| 4 | +> 版本定位:v0.9.x 小版本 |
| 5 | +> 状态:已获用户批准(四节分节确认) |
| 6 | +
|
| 7 | +## 1. 背景与问题 |
| 8 | + |
| 9 | +会话详情「画面要点(OCR)」存在五类质量缺陷(会话 34 实测): |
| 10 | + |
| 11 | +1. **水印混入**:屏 2 中 "CHAN GE WAY PROJECT MANAGEMENT" 属于水印却进入画面要点——水印检测为"全局累积型"(同文本 ≥5 次 + 跨度 ≥60s + 整帧签名 ≥2 种),短视频段水印出现 1~3 帧即漏网;且按精确文本分组,OCR 文本漂移打碎分组。 |
| 12 | +2. **字幕混入**:部分内容属于字幕却进入画面要点——字幕 ROI 是"播放区域底部 25%"固定位置假设(`region_tracker.rs` `SUBTITLE_BAND_RATIO=0.25`),视频内嵌字幕位置偏高时以 `region=full` 身份混入。 |
| 13 | +3. **屏序错误**:一上来就是"屏 2"——屏号采集时分配(原料层事实),消费端过滤链(低分/UI 垃圾/水印/单字符/边缘条带/视频页共现)把屏 1 全部块清空后,第一个幸存屏显示原料屏号 2。 |
| 14 | +4. **屏数缺少**:少了一页(参考图集有图但画面要点无内容)——三嫌疑:整屏被过滤链滤光 / `merge_zero_span_screens` 误并 / ADR-011 触发链路未触发 OCR。 |
| 15 | +5. **结构图中折**:结构图被水平切碎——`layout_analyzer` 行投影按"墨迹行带"切分,结构图内部空白行导致切成多个水平带,每带独立裁剪 OCR,`line_merge` 无法还原整体;图片保护仅对低密度(<6%)生效,有文字的结构图密度高被判 Text 切碎。 |
| 16 | + |
| 17 | +另有**会话/笔记序号断档**问题:`sessions.id`/`notes.id` 为 `INTEGER PRIMARY KEY AUTOINCREMENT`(永不重用),删除会话 14 后新会话从 15 开始,无补位。 |
| 18 | + |
| 19 | +## 2. 产品决策(头脑风暴结论) |
| 20 | + |
| 21 | +| # | 决策点 | 结论 | |
| 22 | +|---|--------|------| |
| 23 | +| D1 | 画面要点核心价值 | 提供视频所示内容:**线性内容直接 OCR 识别,非线性内容截取原图** | |
| 24 | +| D2 | 识别/截取判定标准 | **凡是本地无法准确识别的内容 → 截取原图**(判定权交给识别结果而非静态分类) | |
| 25 | +| D3 | 截取实现方式 | **自动判别 + 自动裁剪**(前置粗判 + 后置兜底双保险) | |
| 26 | +| D4 | 结构内容策略 | 表格/公式/流程图统一**截原图**(本地保底);云端精修输入源升级为**原图 → Markdown/LaTeX**(从残缺 OCR 文本还原改为从图还原);代码保持 OCR(可读即可);本地 OCR 结果降级为检索辅助 | |
| 27 | +| D5 | 屏卡呈现形态 | **图文并排双显**(图为主体,文本/精修产物为辅助) | |
| 28 | +| D6 | 净化修复范围 | 水印过滤增强、字幕隔离增强、屏序连续化+过滤回调、屏数缺失根因修复——**全部纳入** | |
| 29 | +| D7 | 序号策略 | 内部 id 保持 AUTOINCREMENT 永不重用(引用安全);**显示层独立序号字段 `display_no` + 空闲号回收**(删除 14 后新会话显示 14) | |
| 30 | + |
| 31 | +## 3. 第 1 节:OCR 分流管线(核心改造) |
| 32 | + |
| 33 | +### 3.1 管线 |
| 34 | + |
| 35 | +``` |
| 36 | +帧 → 版面分析(增强)→ 前置粗判 |
| 37 | + ├─ 线性文本带(PPT 正文/板书/代码)→ 现有 OCR 管线 → 屏卡文本(现状保留) |
| 38 | + └─ 图结构区域(表格/公式/流程图/架构图/示意图) |
| 39 | + → 不送 OCR(省算力) |
| 40 | + → 区域原图裁剪保存(复用 db_structures 表 + 结构图区段) |
| 41 | + → 云端精修(用户授权时):原图 → Qwen-VL → Markdown/LaTeX(输入源升级) |
| 42 | + → 离线降级:纯图呈现(图本身即完整产物) |
| 43 | +后置兜底:OCR 结果质量评估(碎片化率/平均置信度/几何分布)不达标 → 补截原图 |
| 44 | +``` |
| 45 | + |
| 46 | +### 3.2 关键改动 |
| 47 | + |
| 48 | +**① layout_analyzer 增强(解决"中折"根因)** |
| 49 | +- 新增**图结构判别**:框线检测(横/竖长线交叉)、箭头/连接线特征、墨迹分布不规则度 → 判为图结构区域(**明确:`RegionKind` 新增 `Diagram` 枚举变体**,`is_structural` 为 true,区域采样权重与 Image 同级——跳过 OCR 直截原图) |
| 50 | +- 新增**相邻区域合并**:行带切分后特征相似且间隙小的相邻带合并为整体区域——结构图不再被水平切碎 |
| 51 | +- **图片保护放宽**:密度阈值从 0.06 提升(有文字的图密度高,不能被当 Text 切碎) |
| 52 | + |
| 53 | +**② region_ocr 分流** |
| 54 | +- 图结构区域跳过 OCR 调用(省算力),直接产出裁剪参数走保存 |
| 55 | +- 线性区域保持现有 OCR |
| 56 | +- `schedule_regions` 权重表扩展图结构类型 |
| 57 | + |
| 58 | +**③ 精修输入源升级** |
| 59 | +- 现有精修链路(OCR 扁平文本 → AI)信息已丢一半 |
| 60 | +- 改为"区域原图 → Qwen-VL → Markdown/LaTeX"(表格格线/公式上下标可见) |
| 61 | +- 消费现有 `refine_screen_structures` 接线,只换输入源 |
| 62 | + |
| 63 | +**④ 屏卡呈现(图文并排双显)** |
| 64 | +- 每屏卡片:图(自动裁剪的区域图或整屏图)+ 文本(线性 OCR)+ 精修产物(结构部分) |
| 65 | +- 手动"框选截取"(REQ-184)保留,降级为自动判别的补充手段 |
| 66 | + |
| 67 | +### 3.3 涉及文件 |
| 68 | + |
| 69 | +| 文件 | 改动 | |
| 70 | +|------|------| |
| 71 | +| `layout_analyzer.rs` | 图结构判别 + 区域合并 + 图片保护放宽 | |
| 72 | +| `region_ocr.rs` | 图结构区域分流(不 OCR 直接裁剪) | |
| 73 | +| `structure_capture.rs` | 自动裁剪复用 + 批量捕获 | |
| 74 | +| `artifact_templates.rs` / 精修链路 | 输入源从 OCR 文本 → 区域原图 | |
| 75 | +| `screens.rs` / `screen_merge.rs` | 屏卡结构块携带区域图引用 | |
| 76 | +| `SessionDetailPanel.tsx` | 图文并排双显渲染 | |
| 77 | + |
| 78 | +## 4. 第 2 节:净化修复(4 项) |
| 79 | + |
| 80 | +### 4.1 水印过滤增强(解决 "CHAN GE WAY" 类漏网) |
| 81 | + |
| 82 | +- **双轨检测**:保留现有全局检测(常驻台标/角标)+ 新增**局部时间窗检测**——任意 30s 窗内同文本出现 ≥3 帧即候选(短视频段水印命中) |
| 83 | +- **文本漂移容差**:分组从"精确相等"改为"相似归组"(编辑距离/最长公共子串 ≥ 阈值) |
| 84 | +- **防误杀**:保留"整帧签名多样性 ≥2 种" + 新增"区域一致性"(bbox 位置稳定——正文位置漂移、水印固定) |
| 85 | +- 阈值走 `PurifyConfig` 可校准;原料层不动可复查 |
| 86 | + |
| 87 | +### 4.2 字幕隔离增强(解决"内嵌高字幕混入") |
| 88 | + |
| 89 | +消费端**动态字幕特征判定**(不依赖位置假设),屏内文本块同时满足: |
| 90 | +- 跨 ≥2 帧出现、bbox 位置稳定 |
| 91 | +- 该位置文本帧间变化(字幕随语音滚动,正文静止) |
| 92 | + |
| 93 | +→ 判定为字幕带内容,从画面要点排除(即使 `region=full`)。原料层不动可复查。 |
| 94 | + |
| 95 | +### 4.3 屏序连续化 + 过滤回调(解决"一上来就是屏 2") |
| 96 | + |
| 97 | +- **消费端重编号**:`build_screens` 输出按 `first_seen_ms` 排序后重编号 1..N——显示永远连续,不暴露原料屏号断档(原料层保留原 screen_id 供复查) |
| 98 | +- **过滤链回调**:复查 `edge_strip`(边缘条带)与 `frame_junk_min_hits`(视频页共现)阈值——整屏被滤光的常见元凶,回调后屏 1 不再消失 |
| 99 | +- 重编号为纯显示语义,屏内 `raw` 明细仍可对照原料 |
| 100 | + |
| 101 | +### 4.4 屏数缺失根因修复("少了一页") |
| 102 | + |
| 103 | +先诊断后修(用会话 34 实测数据): |
| 104 | +- 原料有块 → 被过滤链滤光 → 归入 4.3 过滤回调解决 |
| 105 | +- 原料无块 → OCR 未触发(ADR-011 网格 diff 阈值/2s 冷却)→ 修触发链路 |
| 106 | +- 原料有块但被 `merge_zero_span_screens` 并入邻屏 → 复查合并条件 |
| 107 | +- 修复后补回归测试(合成屏数据覆盖三种根因) |
| 108 | + |
| 109 | +### 4.5 涉及文件 |
| 110 | + |
| 111 | +| 文件 | 改动 | |
| 112 | +|------|------| |
| 113 | +| `watermark_filter.rs` | 局部时间窗 + 漂移容差归组 + 区域一致性 | |
| 114 | +| `screens.rs` / `screen_merge.rs` | 动态字幕特征判定 + 消费端重编号 | |
| 115 | +| `purify_config.rs` | 新阈值项(可校准) | |
| 116 | +| `live_frame_process.rs`(如诊断指向触发链路) | OCR 触发条件复查 | |
| 117 | +| `SessionDetailPanel.tsx` | 屏号显示用重编号 | |
| 118 | + |
| 119 | +## 5. 第 3 节:显示层序号补位(display_no) |
| 120 | + |
| 121 | +### 5.1 方案 |
| 122 | + |
| 123 | +`sessions` / `notes` 各新增 `display_no` 字段(与内部 id 完全解耦),创建时分配"最小空闲号",删除后该号自然空缺、被下一个新记录回收: |
| 124 | + |
| 125 | +``` |
| 126 | +现状:删除14 → 新会话 id=15,显示"会话 15"(断档) |
| 127 | +新方案:删除14 → 14 空缺 → 新会话 display_no=14,显示"会话 14"(补位) |
| 128 | + 内部 id 仍是 16(引用安全,用户不感知) |
| 129 | +``` |
| 130 | + |
| 131 | +### 5.2 分配规则(纯函数,可单测) |
| 132 | + |
| 133 | +- 创建时:`display_no = 1..MAX 中第一个空缺号`(连续时 = MAX+1) |
| 134 | +- 删除时:无需任何操作(空缺自然被下次分配回收) |
| 135 | +- 迁移:存量数据按现有 id 升序回填 `display_no`(旧会话 1..N 编号不变,零回归) |
| 136 | + |
| 137 | +### 5.3 关键实现点 |
| 138 | + |
| 139 | +| 点 | 方案 | |
| 140 | +|----|------| |
| 141 | +| 分配原子性 | 空闲号 SELECT + INSERT 包在同一事务(Db 已有 Mutex 串行化,无并发竞态) | |
| 142 | +| 迁移 | 复用项目现有 `ensure_column` 模式(`ALTER TABLE ADD COLUMN` + 回填) | |
| 143 | +| 显示口径 | 所有 `会话 #N` / `笔记 #N` 界面(开始/停止提示、toast、任务列表、导入完成)改用 `display_no` | |
| 144 | +| 内部引用不动 | 文件路径 `{id}/`、外键 `session_id`、artifact、事件表、任务 `refId` 全部继续用内部 id——display_no 纯显示语义,禁止用于引用 | |
| 145 | +| 历史任务列表 | **明确:任务创建时随快照存 display_no**(避免显示时查询映射);refId 仍存内部 id 供执行引用 | |
| 146 | +| 排序/筛选稳定性 | display_no 是持久值,不随排序方式、筛选、分组变化 | |
| 147 | + |
| 148 | +### 5.4 与"位置型编号"方案对比(为何选持久字段) |
| 149 | + |
| 150 | +| | 持久字段 display_no(选定) | 位置型(ROW_NUMBER 计算) | |
| 151 | +|---|---|---| |
| 152 | +| 删除后补位 | ✅ 新会话=14 | ⚠️ 原15漂移为14,新会话=总数+1(≠14) | |
| 153 | +| 编号稳定性 | ✅ 永久固定 | ❌ 每次删除全体重排 | |
| 154 | +| 实现成本 | 迁移+事务 | 无存储,但语义不满足"补位" | |
| 155 | + |
| 156 | +### 5.5 涉及文件 |
| 157 | + |
| 158 | +| 文件 | 改动 | |
| 159 | +|------|------| |
| 160 | +| `db.rs` / `db_sessions.rs` | schema 迁移(ensure_column)+ 分配逻辑(事务内取空闲号) | |
| 161 | +| `commands_session.rs` / 笔记命令 | 返回结构附带 display_no | |
| 162 | +| 前端提示点(ClassroomPage / SessionsPage / AiTaskPanel / VideoImportPanel 等) | 显示改用 display_no | |
| 163 | +| 测试 | 分配/回收/迁移/并发四条路径单测 | |
| 164 | + |
| 165 | +## 6. 第 4 节:测试计划、风险与验收 |
| 166 | + |
| 167 | +### 6.1 测试计划(Rust 单测 + 前端关键路径) |
| 168 | + |
| 169 | +**① OCR 分流管线** |
| 170 | +- `layout_analyzer`:合成网格——框线+箭头结构 → 图结构判别命中;纯文本行带 → Text;图文混合 → 多区域并存;结构图中部有空白行 → 合并为整体区域(中折回归) |
| 171 | +- 分流:图结构区域不送 OCR(mock 引擎断言调用次数)+ 直接产出裁剪参数 |
| 172 | +- 后置兜底:碎片化/低置信合成块 → 补截原图 |
| 173 | +- 精修接线:区域原图 → 精修产物回填 `structure.rendered` |
| 174 | + |
| 175 | +**② 净化修复** |
| 176 | +- 水印:短视频段(3 帧/30s 窗)命中;文本漂移(相似文本归组);防误杀(老师反复强调句不误杀、正文位置漂移不误杀) |
| 177 | +- 字幕:动态特征判定(多帧同位置+帧间变化 → 排除;静止正文 → 保留) |
| 178 | +- 屏序:过滤后重编号连续 1..N;原料 screen_id 保留可复查 |
| 179 | +- 屏数缺失:三种根因(整屏滤光/零跨度合并/OCR 未触发)各一回归测试 |
| 180 | + |
| 181 | +**③ display_no** |
| 182 | +- 分配:连续递增 / 空缺回收 / 全满时 MAX+1 |
| 183 | +- 删除后回收:删 14 → 新记录 = 14 |
| 184 | +- 迁移:存量数据按 id 升序回填 1..N(零回归) |
| 185 | +- 并发:事务内分配(锁串行,无竞态) |
| 186 | + |
| 187 | +### 6.2 风险与缓解 |
| 188 | + |
| 189 | +| 风险 | 缓解 | |
| 190 | +|------|------| |
| 191 | +| 图结构误判(文字当图截取) | 后置兜底 + 原料层可复查 + 阈值可校准 | |
| 192 | +| 水印增强误杀合法内容 | 区域一致性 + 帧签名多样性双条件 + 可校准 | |
| 193 | +| display_no 与 id 混用(开发期) | 字段名语义明确 + 注释声明"纯显示语义,禁止用于引用" | |
| 194 | +| 迁移破坏存量数据 | 复用现有 `ensure_column` 模式 + 回填事务 + 迁移测试 | |
| 195 | +| 改动面大(三块独立功能) | 按"净化修复 → display_no → 分流管线"顺序分 3 批原子提交,各自可独立验证 | |
| 196 | + |
| 197 | +### 6.3 验收标准(会话 34 实测) |
| 198 | + |
| 199 | +1. "CHAN GE WAY PROJECT MANAGEMENT" 不再出现在画面要点 |
| 200 | +2. 字幕内容不进画面要点(动态特征判定) |
| 201 | +3. 屏序从"屏 1"连续开始,屏数不缺失 |
| 202 | +4. 结构图整图呈现(不再中折),表格/公式走原图级精修 |
| 203 | +5. 删除会话 14 / 笔记后新建 → 编号补位为 14 |
| 204 | + |
| 205 | +## 7. 实施顺序(3 批原子提交) |
| 206 | + |
| 207 | +1. **批 1 净化修复**(独立可验证):水印增强 → 字幕隔离 → 屏序重编号 + 过滤回调 → 屏数根因修复(含回归测试) |
| 208 | +2. **批 2 display_no**(独立可验证):schema 迁移 → 分配逻辑 → 命令层返回 → 前端显示切换(含测试) |
| 209 | +3. **批 3 OCR 分流管线**(核心改造,依赖批 1 的稳定净化底座):layout_analyzer 增强 → region_ocr 分流 → 精修输入源升级 → 屏卡图文双显(含测试) |
| 210 | + |
| 211 | +每批通过 `cargo test` + 前端构建后提交;批 1/批 2 完成即可发布 v0.9.x 中间版本,批 3 完成收尾发布。 |
0 commit comments