跳到正文

前端实现与难点 ​

状态:未准备(代码素材已整理,需本人复现与口述)

实现概览 ​

源码根目录:SimulSpeak1。路径均相对该目录。

  • 连接层:frontend/src/ws/WsClient.ts 负责 WebSocket 消息和心跳,frontend/src/rtc/RtcClient.ts 负责媒体与 PeerConnection。
  • 会话层:frontend/src/session/useSession.ts 编排建立连接、停止、错误和清理。
  • 状态层:frontend/src/state/subtitles.ts 使用 Zustand,通过纯函数处理字幕更新。
  • 视图层:SubtitlePanel.tsx、SubtitlePiPPanel.tsx、ControlBar.tsx 等组件位于 frontend/src/components/。

难点与取舍 ​

1. 多来源字幕迟到覆盖 ​

  • 具体问题与背景:ASR、TMT、LLM 的阶段结果异步到达,旧 partial 或快翻结果可能迟于终态 / 纠错结果。
  • 我的实现(候选,待确认):按句子 ID 合并字幕,拒绝部分终态回退和低优先级覆盖,利用 final、engine、revised 标记控制展示;对 TMT partial 按句节流。
  • 备选方案:每个事件直接追加一行;只按最后收到的消息覆盖。
  • 选择理由与限制:保留同句更新关系,兼顾快速反馈与后续修订;不是任意乱序下的全局一致性协议,其他分支仍需逐项验证。
  • 结果与验证方式:使用已有测试核对“终态后收到 partial”“纠错后收到 TMT”“缺失 ID”“裁剪”等情形;测试文件存在,本次未运行。
  • 代码路径 / 证据:frontend/src/state/subtitles.ts、frontend/src/state/subtitles.test.ts。

2. 媒体与连接生命周期 ​

  • 具体问题与背景:采集授权和连接建立是异步过程,用户可能在准备期间停止,卸载后也需要释放资源。
  • 我的实现(候选,待确认):用 useSession 统一清理订阅、WebSocket、RTC 和音频可视化,检查停止标记;RTC 关闭时停止持有的媒体轨道。
  • 备选方案:将采集、握手和 UI 状态全部放进页面组件。
  • 选择理由与限制:让连接层与组件职责分开,便于注入假对象测试;不能据此宣称已实现自动重连或断线恢复。
  • 结果与验证方式:连续开始 / 停止、授权期间停止、页面卸载后检查麦克风指示和活动连接。
  • 代码路径 / 证据:frontend/src/session/useSession.ts、frontend/src/rtc/RtcClient.ts 及 RTC 测试。

3. 画中画与跨窗口清理 ​

  • 具体问题与背景:用户切换到其他页面时仍想看字幕,需要独立窗口和一致的展示。
  • 我的实现(候选,待确认):使用 Document Picture-in-Picture,创建 React root 并注入样式;监听 pagehide,关闭时卸载 root、移除容器和监听器。
  • 备选方案:普通弹窗;页面内浮层。
  • 选择理由与限制:适合持续观看字幕;API 有浏览器支持限制,代码先探测能力并给出不支持提示。
  • 结果与验证方式:检查反复开关、主窗口停止、子窗口关闭、不支持浏览器等场景。
  • 代码路径 / 证据:frontend/src/pip/documentPiP.ts、frontend/src/pip/documentPiP.test.ts、frontend/src/components/SubtitlePiPPanel.tsx。

待完善项 ​

  • 自动滚动:结合 SubtitlePanel.tsx 与 subtitleScroll.ts 复现阅读历史时的行为,确认后再表述为体验成果。
  • 执行前端已有测试与构建,保存输出;当前不写测试全部通过或覆盖率。
  • 性能待测:固定字幕事件回放,使用 React Profiler 比较提交次数、耗时与长会话内存;保留配置上限不等于性能提升比例。
  • 本人需确认实际实现模块,保留能解释的 3—4 条简历要点。

理解机制,讲清取舍,用复盘检验掌握。