Skip to content

Commit 1545bea

Browse files
committed
docs(ocr): 画面要点屏卡体系设计(ADR-015+REQ-155~161 登记)
1 parent 69bd058 commit 1545bea

3 files changed

Lines changed: 222 additions & 0 deletions

File tree

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# ADR-015: 画面要点屏卡体系(screen_id/bbox 落库 + 屏聚合纯函数 + 派生屏视图)
2+
3+
## 状态
4+
5+
已接受(2026-08-20 用户头脑风暴裁决:路线 A+B+D,屏段落+配图;规格见
6+
[archive/2026-08-20/brainstorming-ocr-screen-cards.md](../archive/2026-08-20/brainstorming-ocr-screen-cards.md))
7+
8+
## 日期
9+
10+
2026-08-20
11+
12+
## 背景
13+
14+
用户反馈"画面要点(OCR)提取的内容零碎(时间整理和识别内容)"。会话29 实证(221s / 34 段转写 / 175 块 OCR):
15+
16+
1. **时间碎片**:同一 PPT 内容在 12 个时间戳重复(OCR 截断抖动使 `same_texts` 精确集合去重失效)。
17+
2. **内容碎片**:一屏拆成 15~30 个小块(图注标签 + det 断行),逐块落库展示。
18+
3. **污染**:直播平台 UI(`1人正在看`/`发送`/频道名)+ 用户自己的 IDE/浏览器内容混入(全帧 OCR 无前台窗口过滤)。
19+
4. **落库丢位置**:`session_ocr_blocks` 无 bbox 列——行合并/版面角色/位置去重无法事后进行。
20+
21+
根因:画面要点缺"屏"(幻灯片/画面帧组)这一中间抽象——课堂记忆的天然单位是屏,当前是**块流**直接进列表。
22+
23+
约束:旧数据兼容(历史会话 screen_id/bbox 均为 NULL);原料层可逆(ADR-006 派生视图传统);本地优先(图像不出本机);AI 精修属 v0.8.0 范围不提前引入。
24+
25+
## 决策
26+
27+
1. **`session_ocr_blocks` 加两列**(`ensure_column` 幂等迁移,先例 ADR-014):
28+
- `bbox TEXT`(JSON `{x,y,w,h}`,帧坐标系;NULL=旧数据)
29+
- `screen_id INTEGER`(采集时分配的屏号;NULL=旧数据无屏)
30+
- 实时(live_keyframes/handle_full_frame)与导入(import_frame)**双入口同口径双写**(延续 REQ-117 双入口统一原则)。
31+
32+
2. **不建新表,屏为派生视图**:屏 first_seen/last_seen/成员块 = `GROUP BY screen_id` 聚合查询;旧数据(screen_id NULL)走纯函数 `cluster_blocks_into_screens`(时间 gap>3s 或相似度<阈值 → 分新屏)聚类兜底——零冗余、可逆、旧数据自动兼容。
33+
34+
3. **屏聚合/去重/组织逻辑全部收敛为纯函数模块 `screen_merge.rs`**(normalize / screen_similarity / cluster_blocks_into_screens / line_merge / classify_roles),在线侧 `ScreenTracker`(内存状态机,版面指纹变化=新屏,layout_cache 复用)与离线聚类共用同一套逻辑——在线/离线一致性由构造保证(延续 REQ-081"单一管线双出口"原则)。
35+
36+
4. **采集治理**:全帧路径复用 `roi_tracker.foreground_foreign()`(REQ-084 字幕先例)——前台≠目标窗口期间画面要点不落库;`ui_junk.rs` 黑名单扩充直播互动元素模式。
37+
38+
5. **消费端契约 `SessionScreen`**:`{session_id, screen_id, first_seen_ms, last_seen_ms, title, body, labels, image_ref, structure}`;`SessionDetail.screens` 后端聚合;笔记画面要点 = 屏段落 + full 图内联引用(asset protocol 已 enable)。
39+
40+
6. **结构识别接线**(表格/公式/代码区域):抽纯函数 `refine_screen_structures(screen)` 复用 commands_refine_inner 候选识别逻辑(REQ-049/050 内核不动),会话停止后批量精修,屏卡内渲染 Markdown/LaTeX/代码块;失败降级徽标。
41+
42+
7. **降级四级链**:新数据全能力 → 旧数据聚类屏(无行合并/角色/结构)→ refine 失败徽标 → 现行文本列表兜底(零回归)。
43+
44+
## 备选方案
45+
46+
### 方案 A:实时屏 ID 落库 + bbox 双写(决策 1+3 的在线部分,选定)
47+
- 优点:语义最准(翻页即新屏);live:ocr 可按屏推;图集按屏管理;消费端查询简单。
48+
- 缺点:采集侧状态机复杂度(屏相似判定在线做);需迁移。
49+
50+
### 方案 B:纯事后聚类(不落库)
51+
- 优点:零迁移、可逆、旧数据全兼容。
52+
- 缺点:无 bbox 做不了行合并/版面角色/位置去重;查询每次重算;实时流无法按屏推。
53+
54+
### 方案 C:新建 session_screens 表(屏元数据独立存储)
55+
- 优点:屏元数据显式化,可携带图引用/精修状态。
56+
- 缺点:多一张表 + 双写事务;屏 first/last/成员可由 GROUP BY 派生,YAGNI(决策 2 拒绝)。
57+
58+
### 方案 D:AI 精修屏内容(OCR 文本走云端)
59+
- 优点:整理质量上限最高。
60+
- 缺点:依赖 v0.8.0 AI 层排期;本版范围纪律拒绝,明确留给 v0.8.0(与 REQ-141 精修管线对接,图像永不出本机)。
61+
62+
## 选择理由
63+
64+
- 方案 A 的在线语义 + 方案 B 的旧数据兜底结合(决策 3 共用纯函数)以最小 schema 变更覆盖碎片化根因,且保持原料可逆与双入口统一。
65+
- 屏为派生视图而非新表:符合 ADR-006 派生视图传统,零冗余,避免双写不一致风险。
66+
- 结构识别内核(SLANet/FormulaNet/refine 链路)已就绪,本 ADR 只补消费端接线——投入产出比最高。
67+
- 范围纪律:AI 精修、持久元素自学习、章节检测升级明确排第二波/后续版本,不在本版膨胀。
68+
69+
## 影响与风险
70+
71+
- **性能**:GROUP BY screen_id 聚合 + 屏相似度比较在查询层——会话 ≤200 块量级可忽略;聚类兜底仅在 screen_id NULL 会话触发一次(命令层缓存或惰性派生)。
72+
- **迁移**:加列幂等(ensure_column 先例);旧库只读不受影响。
73+
- **误合并风险**:line_merge 保守阈值(y 差≤行高×0.6 + x 间隔≤半字宽),屏卡可展开块级明细复查(原料不动,可逆)。
74+
- **隐私**:配图引用为本地 asset://(scope $APPDATA/**),图像不出本机(本地优先铁律);AI 精修本版不做。
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# 画面要点(OCR)屏卡体系——头脑风暴与设计规格
2+
3+
**状态**: 已裁决(2026-08-20 用户头脑风暴:路线 A+B+D,屏段落+配图)
4+
**关联**: [ADR-015](../../adr/ADR-015-screen-cards-ocr.md)(架构决策)· 需求池 REQ-155~161 · 会话29 实证(本机 `entropy.db`)
5+
**触发**: 用户反馈"画面要点(OCR)提取的内容零碎(时间整理和识别内容)"
6+
7+
---
8+
9+
## 一、问题实证(会话29:221s / 34 段转写 / 175 块 OCR)
10+
11+
| 现象 | 数据证据 | 根因 |
12+
|------|---------|------|
13+
| **时间碎片**:同一 PPT 内容在 12 个时间戳重复 | `为什么`/`为什么高手管`/`为什么高手管理者思路特别清晰?` 三种截断变体;`系统思维` 等 8+ 次出现 | 去重是"整帧文本集合精确相等"(`same_texts`)——截断抖动使集合永不相等,去重失效 |
14+
| **内容碎片**:一屏拆成 15~30 个小块 | `要素`、`连接`、`功能/目标`(图注标签);长句被 det 切两半:`…相互作用的若干要`+`素组成的表现出新功能的整体` | 无"屏"抽象:块是 det 单行,直接逐块落库展示 |
15+
| **平台 UI 污染** | `X`、`1人正在看`、`发送`、`清晖项目管理`(频道名)、`Chanyovey Prujoct ugt r an`(logo 乱码) | 黑名单只覆盖播放器时间码/水印/编辑器/应用 UI,无直播互动元素模式 |
16+
| **其他窗口污染** | `wsh ·Co`、`commit and push…`、`给智能体发消息`、`Full access`(用户自己的 IDE/浏览器) | 全帧 OCR 无前台窗口过滤(字幕路径已有 REQ-084 先例) |
17+
| **时间戳无区间** | 每块时间戳=识别时刻,无"出现→消失"语义 | 屏级 first_seen/last_seen 缺失 |
18+
| **落库丢位置** | `session_ocr_blocks` 只有 text/score/region/region_kind,无 bbox | 全帧块落库时丢弃 `OcrBlock.bbox`(内存链路可用,TD-046 坐标反算已有先例) |
19+
20+
**核心洞察**: 画面要点缺"屏"(幻灯片/画面帧组)这一中间抽象。课堂记忆的天然单位是屏(老师翻到哪页我记哪页),而当前是**块流**直接进列表。一次翻页(FrameSwitch 事件已有)就是一张新屏。
21+
22+
## 二、头脑风暴全景(按管线环节)
23+
24+
| 环节 | 思路 | 收益 | 代价/风险 |
25+
|------|------|------|-----------|
26+
| **1. 采集治理**(少收垃圾) | 1a 前台窗口过滤扩展到全帧(复用 `roi_tracker.foreground_foreign()`) | 根治 IDE/浏览器污染 | 用户故意切窗看资料会被误杀 |
27+
| | 1b 直播平台 UI 黑名单扩充(`1人正在看`/`发送`/`X`/`下载`/频道名/logo 乱码) | 立竿见影 | 追不上新平台;需启发式兜底 |
28+
| | 1c 持久元素自学习:同 bbox 位置+长期不变小块 → 自动标记 UI | 一帧学会全课过滤 | 依赖 bbox 落库;采集侧状态机复杂度(第二波) |
29+
| **2. 屏级聚合**(块→屏) | 2a bbox 落库(迁移+双写) | 行合并/版面角色/位置去重全可做 | 数据量↑ |
30+
| | 2b 屏 ID 落库:版面指纹变化=新屏(layout_cache 现成);屏带 first/last_seen+成员块 | 时间区间天然形成 | 在线状态机 |
31+
| **3. 屏级时间整理** | 3a 屏内容相似合并:归一化+集合重叠率(吸收截断抖动)→ `00:02–03:23 系统思维…` | 12 时间戳→1 条区间 | 翻回旧页判定(间隔>3s 再出现=新屏) |
32+
| **4. 屏内组织** | 4a 行合并:bbox y 邻近+x 相邻 → 拼接断行 | 内容完整 | 需 bbox |
33+
| | 4b 版面角色:标题(大字/居中)/正文/图注标签 | 卡片可读 | — |
34+
| | 4c 结构识别接线:region_kind=table/formula/code → Markdown 表格/LaTeX/代码块 | OCR 价值跃升 | 消费端接线(识别内核已就绪) |
35+
| **5. 消费端** | 5a 原料屏卡流 + 笔记屏段落+配图 + 大纲/检索按屏 | 全链路一致 | — |
36+
| | 5b 章节检测升级:屏标题变化=精确章节边界 | 更准 | 可选第二波 |
37+
| **6. AI 精修**(可选) | 6a OCR 文本(图像永不出本机)→ AI 整理屏内碎片 | 质量上限最高 | 依赖 v0.8.0 AI 层排期;**裁决不做**,留给 v0.8.0 |
38+
39+
## 三、裁决(2026-08-20)
40+
41+
1. **路线 A+B+D**:屏卡体系 = 采集治理 + 屏ID + 屏级去重合并 + bbox 落库 + 行合并/版面角色 + 结构识别接线
42+
2. **组织策略:混合**——新数据采集时写 `screen_id`+`bbox`;旧数据(NULL)走视图层聚类兜底;在线/离线共用同一套纯函数(ADR-006 派生视图传统)
43+
3. **笔记形态:屏段落+配图**——每屏一段(区间+标题+正文+图注),full 图内联引用(asset protocol 已 enable)
44+
4. **不做**:AI 精修(路线 C → v0.8.0)、持久元素自学习(1c → 第二波)、章节检测升级(5b → 可选第二波)
45+
46+
## 四、设计规格
47+
48+
### 4.1 数据层(自底向上)
49+
50+
- **迁移**(`db.rs` `ensure_column` 幂等,先例 ADR-014):
51+
- `session_ocr_blocks` 加 `bbox TEXT`(JSON `{x,y,w,h}`,帧坐标系;NULL=旧数据)
52+
- `session_ocr_blocks` 加 `screen_id INTEGER`(采集时分配的屏号;NULL=旧数据无屏)
53+
- **不建新表**:屏 first/last_seen/成员块 = `GROUP BY screen_id` 派生查询
54+
- **纯函数模块 `screen_merge.rs`**(原子层,可单测):
55+
- `normalize(text)`:去空白/标点/全角半角统一(吸收截断抖动)
56+
- `screen_similarity(a, b)`:归一化文本集合重叠率(Jaccard)——屏级比较比块级稳定
57+
- `cluster_blocks_into_screens(blocks, gap_ms, sim_threshold)`:旧数据兜底(gap>3s 或相似<阈值 → 分新屏;翻回旧页间隔>3s → 新屏)
58+
- `line_merge(blocks)`:bbox y 中心差≤行高×0.6 且 x 相邻(间隔≤半字宽)→ 同行拼接;否则换行
59+
- `classify_roles(blocks)`:块高≥屏高 4% 或居中大字 → 标题;≤6 字散布 → 图注/标签;其余 → 正文
60+
- **在线侧 `ScreenTracker`**(live_frame_process 挂载,内存状态机):版面指纹变化(layout_cache)→ 新屏;同屏续屏(更新 last_seen 不新增行);落库带 screen_id+bbox;`live:ocr` 事件带屏号
61+
62+
### 4.2 采集治理
63+
64+
- **前台窗口过滤**:全帧路径复用 `roi_tracker.foreground_foreign()`(REQ-084 字幕先例)——前台≠目标窗口期间画面要点不落库
65+
- **UI 黑名单扩充**(`ui_junk.rs`):直播互动元素模式(`1人正在看`/`发送`/`X`/`下载`/频道名/非 CJK 乱码 logo)
66+
- 持久元素自学习(1c):第二波(依赖 bbox 落库后自然支持)
67+
68+
### 4.3 屏内组织
69+
70+
- **屏卡契约 `SessionScreen`**(Rust struct + TS interface 强类型):
71+
```
72+
session_id, screen_id, first_seen_ms, last_seen_ms,
73+
title: Option<String>, // 标题角色块
74+
body: Vec<String>, // 行合并后的正文行
75+
labels: Vec<String>, // 图注/标签
76+
image_ref: Option<String>, // first_seen 时刻 full 图(已有归档机制)
77+
structure: Vec<ScreenStructure>, // {kind: table|formula|code, markdown?/latex?, artifact_ref?}
78+
```
79+
- **结构块**:`region_kind=table/formula/code` 不参与行合并,屏卡内徽标 + 可精修入口
80+
81+
### 4.4 结构识别接线(D 路线)
82+
83+
现状盘点(几乎全现成):region_ocr 已产出 region_kind 块+裁剪图;structure 模型已下载(pp-doclayout-l 129MB / pp-formulanet-s 231MB / slanet_plus_v2 6MB);`commands_refine` 已有"候选识别表格→Markdown / 公式→LaTeX → artifact_blocks"全链路(REQ-049/050)。
84+
85+
- 抽纯函数 `refine_screen_structures(screen)`:屏内结构块 → 复用 commands_refine_inner 候选识别逻辑(command 胶水抽出,可单测)
86+
- **触发时机**:会话停止后批量精修(自动);模型本地无网络依赖;失败降级徽标保留
87+
- **渲染**:屏卡内表格→Markdown、公式→LaTeX、代码→等宽块;产物视图同步消费
88+
- **成本控制**:每屏结构块通常 0-2;无模型/缺文件 → 跳过不阻断
89+
90+
### 4.5 消费端
91+
92+
- **原料视图**(SessionDetailPanel):175 行文本列表 → 屏卡流(时间区间徽标+标题+正文+图注+full 图缩略图+结构徽标);屏卡可展开块级明细(复查误合并);`SessionDetail` 增加 `screens: Vec<SessionScreen>`
93+
- **笔记**(note_filter / NotePreviewView):`ocr_points` 升级为屏段落数组——每屏 `**MM:SS–MM:SS** 标题` + 正文行 + `![…](asset://…/full/{ts}.webp)`(配图可开关);预览过滤统计按屏口径
94+
- **大纲**(outline.rs):屏标题 → 大纲条目(替代文本启发式;无 bbox 旧数据回退现状)
95+
- **检索**(db_ocr_search):命中 → 返回所在屏(区间+图引用)
96+
- **实时面板**:`live:ocr` 带 screen_id,前端"最近画面要点"按屏摘要显示
97+
98+
### 4.6 降级链(四级,本地优先铁律)
99+
100+
1. 新数据(bbox+screen_id)→ 全能力屏卡
101+
2. 旧数据 → 聚类屏(区间成立,无行合并/角色/结构)
102+
3. refine 失败/无模型 → 徽标保留不渲染
103+
4. 全失败 → 现行文本列表兜底(零回归)
104+
105+
### 4.7 测试(AAA,纯函数优先)
106+
107+
- `screen_merge`:normalize/similarity 边界(空集/全等/截断变体)、cluster(gap 分屏/相似合并/翻回旧页)、line_merge(断行拼接/不同行不误并)、classify_roles(标题/正文/标签)
108+
- `ScreenTracker`:mock 块流(新版面=新屏/同屏续屏/UI 变化不扰屏)
109+
- 迁移:加列后旧库可读、新库可写
110+
- note_filter:屏段落输出、配图引用格式、旧数据降级路径
111+
- 真机验收:会话29 重跑 → 175 块 → ~7 屏卡(与 7 张 full 图对应)
112+
113+
## 五、验收标准
114+
115+
- [ ] 会话29 原料视图:屏卡流 ≤10 张卡,每卡带时间区间、无平台 UI/其他窗口污染、正文完整(断行已合并)
116+
- [ ] 笔记画面要点:屏段落+配图,数量与 full 图对应;预览过滤统计按屏口径
117+
- [ ] 旧会话(无 screen_id/bbox):聚类屏正常展示(降级 2 级),零回归
118+
- [ ] 直播平台新会话:UI 元素不进屏卡(黑名单扩充生效)
119+
- [ ] 表格/公式屏:停止后自动精修,屏卡内 Markdown/LaTeX 渲染;模型缺失时降级徽标
120+
- [ ] `cargo test` + `cargo clippy` 全绿;前端构建通过
121+
122+
## 六、需求登记(REQ-155~161,详见需求池)
123+
124+
| REQ | 内容 | 优先级 |
125+
|-----|------|--------|
126+
| REQ-155 | 屏级聚合与去重:screen_merge 纯函数 + ScreenTracker 在线屏 + 旧数据聚类兜底 | P1 |
127+
| REQ-156 | bbox/screen_id 落库迁移:session_ocr_blocks 加列双写(实时+导入双入口) | P1 |
128+
| REQ-157 | 采集治理:前台窗口过滤扩展全帧 + ui_junk 直播元素扩充 | P1 |
129+
| REQ-158 | 屏内组织:行合并 + 版面角色 + SessionScreen 契约 | P1 |
130+
| REQ-159 | 结构识别接线:屏内 table/formula/code → refine → 屏卡渲染 | P2 |
131+
| REQ-160 | 消费端:原料屏卡流 + 笔记屏段落配图 + 大纲/检索按屏 | P1 |
132+
| REQ-161 | 实时面板按屏显示:live:ocr 带 screen_id,最近画面要点按屏摘要 | P2 |

‎docs/product/requirements-pool.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,22 @@
198198
| REQ-146 | 多版本真机验收总清(M0 前置):v0.5.0 M9 / v0.6.0 M7 / v0.7.0 M4 / v0.7.1 验收清单系统执行 + 缺陷清零 | P1 | 已排期 | v0.8.0 | AI 线不盖在未验收地基上;未通过不启动 AI 开发 |
199199
| REQ-147 | AI 链路契约测试:AiRefine/AiEnrich schema 强校验 + mock 适配器全链路 + 降级四路径 + 提示词 golden 冒烟回归 | P2 | 已排期 | v0.8.0 | 前端无 Vitest 基建维持真机手动清单 |
200200

201+
### 待排期 · 画面要点屏卡体系(2026-08-20 头脑风暴裁决)
202+
203+
> 用户反馈"画面要点(OCR)提取的内容零碎(时间整理和识别内容)";会话29 实证(175 块 OCR / 12 时间戳重复 / 平台 UI+其他窗口污染 / 无 bbox 落库)。
204+
> 设计规格 [头脑风暴 OCR 屏卡体系](../archive/2026-08-20/brainstorming-ocr-screen-cards.md) · 架构决策 [ADR-015](../adr/ADR-015-screen-cards-ocr.md)。
205+
> 裁决:路线 A+B+D(采集治理+屏ID+屏级合并+bbox 落库+行合并/版面角色+结构识别接线);笔记形态=屏段落+配图;AI 精修留给 v0.8.0。
206+
207+
| ID | 需求 | 优先级 | 状态 | 目标版本 | 备注 |
208+
|----|------|--------|------|---------|------|
209+
| REQ-155 | 屏级聚合与去重:screen_merge 纯函数(normalize/similarity/cluster/line_merge/classify_roles)+ ScreenTracker 在线屏(版面指纹变化=新屏)+ 旧数据聚类兜底 | P1 | 待排期 | 待排期 | 在线/离线共用同一套纯函数(单管线双出口);翻回旧页间隔>3s=新屏 |
210+
| REQ-156 | bbox/screen_id 落库迁移:session_ocr_blocks 加列(ensure_column 幂等)+ 实时/导入双入口双写 | P1 | 待排期 | 待排期 | bbox JSON {x,y,w,h} 帧坐标系;NULL=旧数据;不建新表(GROUP BY 派生屏) |
211+
| REQ-157 | 采集治理:前台窗口过滤扩展全帧(复用 foreground_foreign,REQ-084 先例)+ ui_junk 直播互动元素扩充 | P1 | 待排期 | 待排期 | 根治会话29 平台 UI/IDE 污染;黑名单扩充+启发式兜底 |
212+
| REQ-158 | 屏内组织:line_merge 断行拼接 + classify_roles 版面角色(标题/正文/图注标签)+ SessionScreen 契约 | P1 | 待排期 | 待排期 | region_kind=table/formula/code 不参与行合并(徽标+精修入口) |
213+
| REQ-159 | 结构识别接线:refine_screen_structures 纯函数复用 commands_refine_inner(REQ-049/050 内核不动)+ 停止后批量精修 + 屏卡 Markdown/LaTeX/代码渲染 | P2 | 待排期 | 待排期 | 模型已本地就绪(pp-doclayout-l/formulanet/slanet);失败降级徽标 |
214+
| REQ-160 | 消费端:SessionDetail.screens + 原料屏卡流(可展开块级明细复查)+ 笔记屏段落配图(asset:// 本地图)+ 大纲/检索按屏 | P1 | 待排期 | 待排期 | 配图可开关;旧数据降级(聚类屏无行合并/角色);大纲无 bbox 回退文本启发式 |
215+
| REQ-161 | 实时面板按屏显示:live:ocr 事件带 screen_id,最近画面要点按屏摘要 | P2 | 待排期 | 待排期 | 一行=一屏摘要(区间+标题) |
216+
201217
### V1.0 · 体验增强(远期)
202218

203219
| ID | 需求 | 优先级 | 状态 | 目标版本 | 备注 |

0 commit comments

Comments
 (0)