外观
前端实现与难点
状态:未准备(代码素材已整理,需本人复现与口述)
实现概览
源码根目录: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 条简历要点。