Skip to content

Pr/rust vr subtitle overlay - #8

Open
KKTIME2024 wants to merge 3 commits into
febilly:mainfrom
KKTIME2024:pr/vr-subtitle-overlay
Open

Pr/rust vr subtitle overlay#8
KKTIME2024 wants to merge 3 commits into
febilly:mainfrom
KKTIME2024:pr/vr-subtitle-overlay

Conversation

@KKTIME2024

Copy link
Copy Markdown

加了什么

  • vr_overlay/:原生 SteamVR 浮层客户端(Rust)。WebSocket 接收字幕 snapshot, DirectWrite 渲染中英日混排,进程由主程序拉起/守护。
  • VR 旁路镜像(vr_subtitle_mirror.py):把头显字幕订阅到桌面浮窗消费的同一条广播流,内容与桌面天然一致。
  • 入口:Settings 里新增"VR 浮层"开关(热切换;开启时桌面浮窗自动让位,关闭自动恢复)。
  • 打包:CI/本地构建自动产出包含 RinBridgeOverlay.exe + openvr_api.dll 的 Windows 发布包;缺 Rust 产物时仅告警,不阻塞构建。
  • 测试:pytest 503 条全绿(含 VR 协议、生命周期、显示模型、配对回归),cargo test 全绿。

VR 字幕设计

显示:两行,各行独立顶替。

┌──────────────┬─────────────────────────────────┬──────────────────────┐
│ 行 │ 内容 │ 顶替规则 │
├──────────────┼─────────────────────────────────┼──────────────────────┤
│ 译文行(大字) │ 最近一句的译文(含 LLM 精译覆盖) │ 只有新译文出现才顶 │
├──────────────┼─────────────────────────────────┼──────────────────────┤
│ 原文行(小字) │ 正在说的原文,live 逐字增长 │ 新句原文直接顶旧原文 │
└──────────────┴─────────────────────────────────┴──────────────────────┘

说 A(原文逐字长)→ A 译文到(进大字行)→ 说 B(只有小字行被顶掉,A 译文不动)→ B 译文到(顶掉 A 译文)。任意时刻画面就两行。

数据:镜像而非第二条管线。 VR 旁路订阅 /ws 的 update / refine_result / clear(桌面浮窗吃的同一份数据)

分句:共用模型 + 后端句 id。 从桌面浮窗抽出共用的 subtitle_model.py(浮窗行为不变);VR 侧额外启用按后端 SentencePairing 盖章的 llm_sentence_id 分行——新句直接换行、live 草稿不会并进已定稿句
子、迟到的译文按 id 归位到自己的句子。桌面端保持原有启发式分句,行为不变。

渲染:恒定单块。 整帧始终是一个 snapshot block(固定身份),槽位写穿更新,位置和缓存全程不动——不会跳动、重叠。

怎么使用

  1. Windows + SteamVR(头显在运行)。
  2. 启动 RealtimeSubtitle,正常配置识别/翻译(与桌面用法完全一致)。
  3. 打开 Settings → VR 浮层,戴上头显即可。浮层跟随头部视野(头锁定,略低于视线中心)。
  4. 可选环境变量:VR_OVERLAY_EXE(指定浮层 exe)、VR_OVERLAY_TOKEN(bridge 鉴权 token)、VR_MIRROR_MODE=false(调试用,回退旧事件线)。
  5. 排查:vr-push.log 与 overlay-logs/ 落在 exe 旁边。

对现有行为的影响

  • sentence_pairing.MAX_WAIT 3s → 8s:容纳 Soniox 迟到译文,避免译文挂错句(桌面同样受益)。
  • overlay_window.py 仅抽取共用模型,渲染无改动;其余为 VR 门控新代码。

许可与来源

  • vr_overlay/, AGPL-3.0,与本项目一致,已加入 ACKNOWLEDGMENTS.md。
  • vr_overlay/vendor/openvr_api.dll 为 Valve SteamVR 运行时 loader(来源与 SHA 见 vr_overlay/vendor/README.md)。

验证

  • pytest 503 / cargo test 全绿。
  • Windows + 头显实机:流式逐字、译文顶替、连续多句、双说话人均符合上表契约。

已知边界(follow-up)

  • 桌面"仅原文/仅译文"显示模式暂未接入 VR;语言小牌(EN/JA/ZH)已在协议中、暂未渲染;头显暂不区分说话人。
  • 头显可见性只能在 Windows + SteamVR 验证,CI 只做构建与单测。

原生 SteamVR 浮层 (vr_overlay/, Rust): WebSocket bridge 接收 snapshot
协议, DirectWrite 渲染 CJK/拉丁字幕, 2-slot 固定行位 (runtime 按句序
喂真实锚点)。附 vendored openvr_api.dll (来源/哈希见 vendor/README.md,
AGPL-3.0, 与本项目许可兼容, 致谢见 ACKNOWLEDGMENTS.md)。

CI: PyInstaller 前先 cargo build --release; spec 条件收集
RinBridgeOverlay.exe + openvr_api.dll (缺输入 → 警告并产出
Python-only exe, 不硬失败)。
… rows)

VR 字幕不再走独立事件线, 直接旁路订阅桌面浮窗消费的同一广播
(update/refine_result/clear), 显示模型 = 一个框两行、各行独立顶替:
- 译文行(主): 最近已译句的译文, 仅被新译文/新 refine 顶替;
- 原文行(副): 当前句原文 live 逐字增长, 新句原文直接顶旧原文;
- 首句无译文时原文兜底大字行。整帧恒定单个 snapshot block
  (恒定 occupant 身份), 位置/缓存全程稳定。

配套:
- subtitle_model.py: 从 overlay_window 提取共用分句模型
  (OverlayWindow 行为不变); VR 侧启用 sid_boundaries —— 按后端
  SentencePairer 盖章的 llm_sentence_id 分行 (新句直接换行, live
  draft 不得并入定稿句, 迟到译文按 sid 归位), 桌面默认关闭。
- Settings 增加 VR 浮层开关 (热切换, 与桌面浮层互斥);
  /vr_ws 鉴权 + snapshot 广播; 进程生命周期由 vr_overlay_manager 管理,
  frozen 模式日志/manifest 落在 exe 旁 (取证可查)。
- sentence_pairing MAX_WAIT 3s→8s: 容纳 Soniox 迟到译文,
  避免译文挂错句 (桌面同样受益)。
- [vr-push] 毫秒级出帧日志 (控制台 + vr-push.log)。
…essions

- test_vr_ws / test_vr_overlay / test_vr_overlay_manager /
  test_vr_overlay_endpoint / test_vr_overlay_config: 鉴权、snapshot
  契约、生命周期、frozen/source exe 路径、env 解析 (reload 抗污染)。
- test_vr_subtitle_mirror: 单块双行模型 — 顶替时序、迟到译文归位、
  迟到 refine 不覆盖新句、clear、恒定身份。
- test_sentence_pairing / test_soniox_session_response /
  test_ipc_server: MAX_WAIT 契约、无条件 finalized 包、VR 旁路门控。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant