摘要

战斗记录 App 有“实时模式”:用户玩游戏时,它每秒截取约 10 帧画面,挑出关键帧,交给识别服务,再把结果累积进状态估计(SE,把观察累积成对局状态和对手构筑推断的模块),最终显示在“简报”里。用户实玩的一段 3 分钟真值显示,App 读到的数值基本都对,但该采到的 47 个画面区间只采到 21 个:例如 16 个生物面板只读到 5 个,8 个信息页在排队中被挤掉。

已有的“离线视频回放”会等识别读完再解码下一帧,复现不了实时的排队。本实验做了一个实时节奏回放工具:用 App 真正的实时路径,只把“截屏”换成“录像在当前挂钟时刻的那一帧”,于是排队、丢帧、挤页都按本机的实时节奏发生。在同一个 3 分钟窗口上,逐项改动调度并前后对比:最终配置采到 42/47,读值 0 错,减员推断全对。

要回答的问题

  1. 实时模式漏采的根子在哪里——采集、调度还是识别?
  2. 哪些调度改动能在不引入错误的前提下提高覆盖、降低等待?

数据与来源

  • 主窗口:一局 23:58 开始的实时对局录像的 600–780 秒,已有三层真值:L1 采到(47 个应采画面区间有没有被读到)、L2 读对(读到的数值对不对)、L3 SE 用对(减员、假兵堆、魔法净变化等推断对不对)。
  • 跨窗口回归:一段 10 月 10 日 16:57 训练录像的真值时间线(含 24 个战斗生物面板、22 次法术书、55 个攻击预览等)。
  • 全部是已曝光的开发录像;真值是模型目视核对(MODEL_VISUAL_CHECKED),不是人工审核(REVIEWED),不是独立准确率。

术语:旁路读取——不排在约 5 秒一次的“会话读取”后面、单独处理的读取通道;信息页——生物面板、法术书、英雄页、日志等弹出页面;行动条——屏幕上方按行动顺序排列的单位卡片;数量牌——战场上部队脚下显示数量的小牌;空读——旁路读取了但没在画面里找到页面。

方法

  • 回放工具只替换两处:截屏改为取录像对应时刻的帧(同样 10 fps、同样 8 帧积压上限);会话直接关联给定录像,不联系用户的录屏器。之后的关键帧服务、场景线索、路由、旁路、SE 都是原代码。
  • 冒烟运行中录像秒与实时媒体秒之差为 −0.033 到 +0.046 秒(中位 −0.009 秒)。
  • 评分复用实时真值的评分脚本(参数化后,默认值重算原实时结果与原文件完全相同)。
  • 每次只加一项改动,与前一次比较;无效或有害的改动撤回。

设置

主要局限先写在前面:这台机器上回放时没有同时运行游戏,CPU/GPU 比实玩宽松,结果偏乐观;只有一个 3 分钟主窗口;回放之间本身有波动(只差一项改动的两次运行可以差 3 个区间)。

结果

主窗口逐步对比(600–780 秒):

实玩 run-01 基线 run-02 信息页一律走旁路 run-03 + 场景线索 4 Hz run-12 最终配置
L1 采到 21/47 36/47 38/47 42/47 42/47
生物面板 / 法术书 / 英雄页 5/16 / 9/14 / 3/6 11/16 / 14/14 / 6/6 12/16 / 13/14 / 6/6 16/16 / 14/14 / 6/6 15/16 / 14/14 / 6/6
信息页等待(画面→读数存好)中位 / 最大 114–523 秒 18.3 / 44.2 秒 2.65 / 7.5 秒 3.35 / 8.6 秒 5.51 / 12.3 秒
L2 错值 2 0 0 1 0
L3 减员找到 / 假减员 / 错值 2 / 0 / 2 2 / 0 / 0 2 / 0 / 0 2 / 0 / 0 2 / 0 / 0
不在行动条上的兵堆减员定位 — 48.1 秒 5.8 秒 48.9 秒 6.2 秒

最终配置 = 信息页走旁路 + 战斗中场景线索 4 Hz + 悬停预览线索 2 Hz + 旁路信息页顺带读数量牌(加 SE“前后同数”假兵堆规则)+ 魔法数字滚动时暂缓读行动条 + 没等到静止就读“最静止的样本”。run-12 的 L2 明细:英雄魔法 212/212、数量牌 70/70、行动条数量 234/234、面板 24/24;空读 32/185(17%)。剩余 5 个漏采:1 个 0.45 秒预览、2 个约 0.5 秒的生物面板(读到淡入淡出帧或那一刻没有帧送到服务)、2 个“英勇攻击”提示(还没有读取器)。

关键发现:

  • run-02 的主要收益是信息页不再排在会话读取后面,等待中位从 18 秒降到 2.65 秒;但代价是信息页不再顺带读战场数量牌(段内 108→14 次),不在行动条上的兵堆只能靠数量牌。
  • 在保留的旁路信息页原图上离线试读数量牌:89 页、833 个读数中 746 对、2 错、85 无真值,于是把“旁路页顺带读数量牌”接入(run-07),不在行动条上的活化盔甲减员定位从 48.8 秒恢复到 6.2 秒。
  • 新出现的一个假兵堆(身体被认错兵种、但数量与另一堆相同)促成 SE 补充规则:同方另一堆在这次读数前后最近的读数都是这个数,也算同数。用原四局复算,真兵堆保留数和被分出的假兵堆数与改动前完全相同。
  • 魔法滚动暂缓消除了 606 秒处的魔法读数边界错误(run-11:HUD 魔法 212/212,0 次魔法来回跳动)。

跨窗口(16:57 训练局,严格计数): 实时节奏 run-09 生物面板 24/24、法术书 21/22、预览 49/55,行动条等待中位 0.12 秒;但信息页等待 p95 达 16.05 秒(最多同时排队 6 张)。同一最终配置的离线视频回放首次读全所有真值页面类型(生物面板 24/24、法术书 22/22、日志 9/9,预览 51/55)。

新鲜度(run-13): 画面出现 → 进入简报:行动条中位 3.64 秒、信息页 5.96 秒(p95 11.47 秒)、会话读取 4.07 秒、预览 1.80 秒;每条读数都进入了简报,主要等待在信息页排队。

界面线程卡顿: 每次刷新只组装一次 SE 请求后(run-15),超过 0.25 秒的卡顿从 249 次降到 222 次,超过 1 秒的从 2 次降到 1 次。快照节流(最多每 12 秒保存一次,结束/切换/关闭时立即保存)把一局快照从 243 份降到 36 份;节流前先核对过:不用任何快照、只靠会话记录就能重建与最后快照逐帧相同的 SE 请求。

失败与负结果

  • 战场关键帧间隔 40→20 秒(run-04): 学习型选择器在战斗中本来就很少选战场帧,间隔只是上限;只多了 6 次会话读取,评分窗口里一次都没有,反而挡住旁路,信息页等待翻倍(3.35→7.18 秒)。撤回。
  • 悬停预览线索 2→4 Hz(run-05): 窗口里的 3 个短预览仍是 0/3,整局只多读到 2 次预览却多了 6 次读取,信息页等待变长,且界面线程每次多约 16 毫秒。撤回。(只差一项改动的 run-06 预览为 2/3,说明 3 个样本的波动很大,撤回依据是成本而不是这 3 个预览。)
  • 预览挑帧(run-10): 读到预览牌的比例略升(66%→70%),但真值预览 49→48,等待中位多 0.8 秒;“白色像素多”不等于是同一次预览最完整的一帧。撤回。
  • 法术书静止间隔 0.45 秒: 实时和离线都没有改善(离线 20/22 与修改前完全相同),空读却升到 21%,超过 20% 预警线。撤回,改为“读最静止的样本”。
  • 度量本身的错误: 等待统计原来按先后顺序配对“排队/取走”事件,实时模式下被替换的帧会让配对整体错位,一度算出行动条等待中位 46 秒(假的);改为按同一帧的画面秒配对后为 0.12 秒。
  • 被自身负载污染的运行: run-16、run-17 期间同时在跑测试和发布构建,卡顿、丢帧和挤页(run-17 挤掉 17 页)都不能归因于对应改动;能确定的只有节流生效、SE 结论全对。run-18(16:57 整段回放)期间游戏进程一直开着,覆盖略降(生物面板 22/24、预览 44/55)、卡顿明显增多,正说明实玩需要单独测量。
  • 有界 CPU 负载(run-08): 4 个进程各占 70% 的 CPU 负载下没有看到退化,但没有模拟 GPU 和内存带宽。

局限

  • 回放机器上没有游戏负载,结果偏乐观;实玩效果尚未验证。
  • 只有一个 3 分钟主窗口和一段训练局回归;真值是模型目视核对。
  • 信息页“最新优先”调度只做了只读评估:约四成读取发生时同类更新的一页已在排队,但队列没有挤掉任何一页,改调度只会把新鲜度在新旧页之间挪动,因此暂不改动。

结论与下一步

实时漏采的主要原因是调度:信息页排在慢速的会话读取后面。让信息页走旁路、提高场景线索频率、在旁路页上顺带读数量牌,把同一窗口的采集从 21/47 提升到 42/47,且读值和减员推断没有出错。外部审阅建议支持以这套配置准备候选版本,在用户批准后实玩,测量采集完整性、信息新鲜度(画面时间、识别完成、进入简报)、界面和游戏流畅度、长局稳定性。干净对照的复测仍待完成。