摘要

游戏有一个战斗日志(Logs)窗口,每行写着时间、哪位玩家、发生了什么(例如谁攻击谁、造成多少伤害)。程序要从录像里用 OCR(光学字符识别)把这些行读出来。前一个实验(B071)发现:日志刚出现时颜色较淡,读这一帧时 4 个玩家名字被读错;200 毫秒后同一内容已经变清楚,读就全对。问题在于 OCR 读一次大约要 361 毫秒,等读完发现有问题再去截图,画面可能已经滚动了。

本实验 B072 做了一个很小的调度组件:读取期间把后来到达的稳定帧暂存起来(最多两张),首次结果出现明显格式缺损时,立刻改读暂存的较新帧。在训练数据上,同样 114 行日志的“时间、玩家、正文三项全对”从 108 行提高到 113 行;代价是读取次数从 40 次增加到 55 次。这是只在 Perception 内部的私有候选组件,没有接入默认 App 或视频流程。

要回答的问题

在读取较慢的前提下,保留读取期间到达的稳定帧并允许有限重试,能否补回原本错过的清楚日志画面?成本多大?会不会引入新错误?

数据与来源

  • 训练:B071 用过的两个 50 秒来源组,共 500 个原生帧,复用当时每帧真实的检测框(不是参考框)。
  • 评分:四组相同日志内容的 114 条完整行,作为固定分母;七张相关原图上出现过 199 条完整行,其中四张复用 B071 的精审标签,三张后续图重新看原图确认内容相同。其余读到的文字只是草稿,不算精标。
  • 冻结后检查:另一个已曝光来源的 8 秒、80 帧(与训练组无交集)。历史上已曝光,不算新盲测;从未曝光的冻结来源没有打开。

方法

两个新组件:

  1. 读取反馈:只看读出的结果是否有明显格式缺损——空结果、时间或前缀格式坏了、句末缺结束标点——有就提示“值得重试”。它不修改任何字,不依赖玩家名单或标签。通过检查不代表全文正确:错数字、整行遗漏仍可能通过。
  2. 有界缓存:同一时刻最多 1 个请求在读、2 张原图在等;等待最长 1000 毫秒;同一内容最多读 2 次。等待中的同内容帧会被最新到达的稳定帧替换(“最新”不保证更清楚),替换后按截图时刻排序。溢出、过期、到达重试上限都单独计数。面板关闭后,此前留下的短内容仍可读取,结果保留原截图时刻。

三种策略对照:

名称 行为
完成即确认,无缓存 忙时丢弃新帧,任何读完的结果都算确认
格式反馈,无缓存 忙时丢弃新帧,有格式缺损则允许之后重试
格式反馈 + 有界缓存 上面的反馈,再加等待缓存

设置

三种策略收到完全相同的稳定帧提议;同一张图同一个框只真实跑一次 OCR,结果和实测耗时在三种策略间共享,避免 OCR 噪声不同影响比较。共 66 次独立原生 OCR(另有 1 次热身),稳定提议 349 次。

采用离散事件重放:把每次实测 OCR 耗时当作服务时间,结果在“完成时刻”之后才可用。这不是真实的实时线程或 App 整链路,解码和面板检测时间没有计入。

结果

训练对照(114 行固定分母):

策略 读取次数 第二次尝试 三项全对 玩家正确 正文正确
完成即确认,无缓存 40 0 108 110 112
格式反馈,无缓存 44 4 109 110 113
格式反馈 + 有界缓存 55 12 113 114 113

三种策略的时间字段都是 114 行全对。

一次具体的恢复过程:

  • 派发一张较淡的帧,实际读取约 379 毫秒;结果中两条前缀坏了(触发重试提示),四个玩家字段有误。格式检查并不知道答案,也没定位出全部四处错误。
  • 读取期间又到了两帧,缓存保留了最新的那张稳定帧。
  • 收到失败反馈后立即读缓存帧,结果 29 行时间/玩家/正文全对,距首次派发 704 毫秒。
  • 两个无缓存策略只能等到页面已经滚动后的帧,没拿到这次展示的清楚画面。

原先那张帧的四处错误不会被改写成正确,两次截图和结果都分别保留。

冻结后另一来源:三种策略都只在已审清楚区间内读了一次,28 条事件行时间/玩家/正文全部正确,没有选到过渡帧。

成本:读取 40→55(+37.5%);有缓存策略 55 次中 29 次带格式提示。缓存峰值 1 在读 + 2 等待,原图像素约 31.64 MiB(不含模型和进程内存)。训练 OCR 服务时间 p95 约 0.436 秒;按此重放,缓存候选“截图→结果”p95 约 555 毫秒、最大 573 毫秒。这些都不含检测、解码和 App,不能说明产品 3 秒目标达成。

失败与负结果

  • 回合标题没读对:冻结检查的原图有“第2回合”,OCR 输出多了一个字符,被保留为无法解析的行,回合标题 0/1。格式反馈只检查事件行,没有触发重试。所以 28/28 事件行不等于整页全对。
  • 漏字没修好:训练中有一行“死亡单位”漏了“位”,仍然通过格式检查,保留为失败。
  • 格式提示会漏掉“看起来合法”的错字或错数字、整行遗漏,也可能对滚动边缘的半截行反复重读。
  • 第二次尝试也可能失败,不能把增加的读取次数都算作“修好”。

局限

  • 只在有限两个来源上有效,不证明短提示、魔法书或状态栏也适用。
  • 整段 500 帧、所有滚动位置都没有金标准,不报告整体召回。
  • 事件重放不是实时实现。新增 27 项调度/格式测试,相关共 103 项通过;500 帧、139 次请求的调度逐条重放一致。完整 Perception 套件没有重跑。
  • 没有更改默认配置、App、游戏或其他模块。

结论与下一步

“读取期间留住后来的清楚帧、有缺损时重试”能补回一种真实存在的漏读组合,作为显式候选保留。下一步:把滚动边缘的残行和正文缺损分开,减少无效重试;确认回合标题和格式良好的错字不会因“没有提示”就被当成确认;然后用真实录像工具验证截图、检测、OCR 调度的全部成本,而不是只用事件模拟。