Serve replay playback from a cached analysis result

Replay re-ran the SDK chain on every seek; Part A's pass stores the flow
samples once. Opening a recording now reuses a compatible result or runs the
pass behind a progress/cancel surface, and one cursor with two modes
(recorded CSV, analysed) feeds the charts, the 2D canvas and the 3D pane by
frame id. A threshold, colour or idle-dot change redraws from the stored
frames and writes nothing; a cancelled pass is reported and never played.

Verified: apps/studio/tests 440 items / 0 failed / 18 skipped (15 new, no
existing assertion changed); shared 417 / 0 / 1; autocal 358.
This commit is contained in:
ykcheungab
2026-10-04 13:38:03 +08:00
parent b6f6a06851
commit cf49b0836e
11 changed files with 2731 additions and 29 deletions
+38 -4
View File
@@ -155,7 +155,8 @@
"units_newton": "牛顿",
"units_raw": "原始",
"settings": "设置",
"settings_tip": "展开或收起单位、记录模式与预览"
"settings_tip": "展开或收起单位、记录模式与预览",
"stopped_analysis": "分析"
},
"units": {
"newton_short": "N",
@@ -218,7 +219,10 @@
"mesh3d_rejected": "三维场景被拒绝:{message}\n只影响三维视图:采集、记录与力曲线照常工作。",
"mesh3d_unavailable_gl_reason": "本机无法使用三维显示:{reason}\n采集、记录与力曲线照常工作。",
"mesh3d_settings_tip": "三维显示设置(视角、外壳、色标、显示频率)",
"mesh3d_reset_tip": "复位视角:回到场景自带的取景"
"mesh3d_reset_tip": "复位视角:回到场景自带的取景",
"analysis_pipeline": "分析结果(已跑完的一遍)",
"analysis_pipeline_tip": "这一帧的箭头来自存下来的分析结果,不是此刻在跑的链路;换阈值只改变哪些样本算「有效」,不会重算。",
"analysis_empty": "分析结果里没有这一帧"
},
"chart": {
"fn": "FN",
@@ -278,7 +282,16 @@
"warn_config_missing": "找不到配置哈希,无法校验重算一致性",
"warn_rows_skipped": "有无法解析的 CSV 行被跳过",
"warn_frames_dropped": "有帧在队列溢出时丢失,仅保留索引记录(回放显示为“该帧未录制”)",
"warn_out_of_order": "该录制由旧版本写入,行序不是时间序;回放已按时间重排,区间边界可能与当时不同"
"warn_out_of_order": "该录制由旧版本写入,行序不是时间序;回放已按时间重排,区间边界可能与当时不同",
"analysis_empty": "这个分析结果里没有可显示的帧",
"analysis_unreadable": "这一帧读不出来({error})",
"analysis_complete": "已用分析结果回放:{frames} 帧,游标按信号时间(录制自己的 frames.csv)",
"analysis_reused": "找到了现成的分析结果,直接回放:{frames} 帧",
"analysis_failed": "分析未完成({reason}):不提供回放。可以重新分析,或关闭「从视频重算」看录制的 forces.csv",
"analysis_cancelled": "分析已取消:未写出完整结果,因此不提供回放",
"analysis_no_source": "这段录制没有可用于分析的视频分段",
"analysis_busy": "分析进行中:先等待或取消当前这一遍",
"analysis_grid_mismatch": "当前显示设置改了采样网格({keys}),存下来的候选位置无法服务它:回放仍按结果自己的网格绘制"
},
"record": {
"label": "记录",
@@ -497,6 +510,27 @@
"severity_info": "提示",
"severity_warning": "警告",
"severity_error": "错误",
"stats": "已显示 {displayed} · 显示跳帧 {dropped} · 合成 {compose} ms · 绘制 {paint} ms"
"stats": "已显示 {displayed} · 显示跳帧 {dropped} · 合成 {compose} ms · 绘制 {paint} ms",
"source_analysis": "分析结果:已跑完的一遍,按帧读取",
"source_analysis_tip": "画面来自存下来的分析结果:算法链路已经跑完并写入缓存,拖动时间轴与播放都只是读文件。换阈值或配色不会重算。"
},
"analysis": {
"title": "正在分析录像",
"subtitle": "只跑一遍:之后拖动时间轴、播放与单步都只是读结果",
"stage_open": "打开链路",
"stage_frames": "逐帧分析",
"stage_write": "写入结果",
"frames": "{written} / {expected} 帧",
"segment": "分段 {index} / {count}",
"elapsed": "已用 {seconds:.1f} s",
"cancel": "取消",
"cancelling": "正在取消…",
"cancel_tip": "取消这一遍:已完成的帧会留下,但结果会被标记为未完成,永远不会被当作有效结果回放",
"reused": "已有结果,无需重算",
"complete": "分析完成:{frames} 帧,用时 {seconds:.1f} s",
"cancelled": "分析已取消({frames} 帧已写完,结果标记为未完成)",
"failed": "分析失败:{reason}",
"incomplete": "结果未完成:{reason}",
"blocked": "正在采集:停止后再分析"
}
}