把系统声音、麦克风或本地音视频,变成一条可回读、可导出的双语会话时间线。Rust Core 负责会话与编排,Swift 原生进程接管 macOS 音频,常驻 Hy-SimulMT 模型做同传翻译。
依赖方向自上而下:simulmt-app → simulmt-core → simulmt-policy / simulmt-api。Core 通过 trait 与子进程隔离音源、翻译器、播放器,HTTP 层不感知任何 macOS 或模型细节。
全仓约 8.4k 行源码,Rust 为骨架,Swift 做 macOS 原语,前端单文件零依赖。
系统的“通用语言”。会话状态机、音频帧、翻译/字幕/播放事件、指标、快照全部在此定义一次,serde 双向序列化,并同步维护 api/proto/simulmt/v1 六份 Proto 契约供外部 Worker 使用。
把音源吐出的 100ms 传输帧拼成模型要求的 800ms 块;BoundedQueue 实现有界队列与溢出策略(拒绝 / 丢最旧),积压统计直接喂给三档语音策略的“跳句”决策。
编排中心。管理多会话与全局模型互斥:prepare 时把其他会话的常驻模型 detach/adopt 过来(reattach 重定向事件、清音频与语言上下文),权重零重复加载。每次 start/resume 创建新运行代际(epoch)。
数据通路:Source → Chunker → Translator → 字幕/TTS 双组句。lifecycle.rs 用 Mutex + CancellationToken 串行化生命周期操作,stop 可取消当前持有门的操作,高频音频路径绝不经过它。
薄薄一层胶水:16 条会话路由(prepare/start/pause/resume/stop/stop-model…)、每会话 WebSocket 事件流、媒体上传经 afconvert 解码为 16kHz WAV、SRT/VTT/WAV 导出。默认只监听 127.0.0.1:8780。
macOS 音频原语封装。CATapDescription 建进程 Tap 或全局立体声 Tap(可排除指定 PID),muteBehavior = .mutedWhenTapped 实现“接管即静音原声”;麦克风走 AVAudioEngine。stdout 只写裸 PCM,日志一律 stderr。
“可预合成、按精确时刻接续”的原生播放器。AVSpeechSynthesizer 生成 24kHz PCM16 WAV 缓存;多 AVAudioPlayer 用 play(atTime:) 设备时钟无缝排播,支持 rate 变速与三档策略联动。
纸感设计的多会话工作台:左侧会话列表、中间双语时间线(真实 TTS 播放事件高亮当前句)、底部控制条(音源/方向/三档策略/模型)。localStorage 只存界面偏好,权威数据全在后端。
为外部 Worker 准备的版本化 Protobuf 契约,与 Rust serde 类型一一对应。改任一侧必须同步另一侧——这是跨语言协作的防漂移锁。
同传系统的难点不是翻译,而是时间:旧数据要丢弃、积压要泄洪、长会话不爆上下文、崩溃要能接上。
每次 start/resume 递增 epoch,每次音源重置递增 source_generation。管线中所有帧与结果都携带三元组 session_id + epoch + sequence,旧代际的翻译与播放结果到达即丢弃——晚到的旧数据不会污染新会话。
上下文占用到 65% 时在空白回合轮换、80% 强制轮换,只携带最近 4 轮双语短上下文。优先进程内轮换(片段 ID 连续),不支持才重启进程;轮换与异常恢复都会重放已写入未确认的音频,一个音节不丢。
跟得紧:短组句、低缓冲、积极追平,严重积压丢最旧语音(字幕保留)。自然流畅:连续调度、温和追平。完整优先:充分组句、原速播放、不跳句。策略同时作用于组句阈值与播放队列,运行中可切。
全局只保一个常驻 llama-mtmd-cli --stream-v2。会话切换时不杀进程,而是 reattach:重定向 stdout 事件流、清空音频缓冲与语言上下文。18 GiB 权重秒级“搬家”。翻译方向切换才重启进程。
系统/应用 Tap 创建时把 TTS 播放器 PID 加入排除列表,译文的合成与播放声音永远不会被采回去再翻译一次;暂停/停止即销毁 Tap、恢复原声,模型保持常驻待命。
字幕 JSONL 追加写、读时按 cue_id 折叠修订;会话清单原子写入。重启后恢复配置、名称、时间与完整字幕,所有运行状态回到 Idle——不伪造仍在采集,也不假装模型还在。
完整音源与播放器仅 macOS;Windows / Linux / 浏览器扩展只保留 trait 适配器边界,Rust Core 无需改动即可移植。
音频、模型、TTS 三者都是独立子进程:各自崩溃可恢复(重连 / 重放 / 重启),Core 与 macOS 细节完全解耦。代价是协议必须双侧同步维护。
HTTP 仅监听本机且无认证;真实音频接管只在用户显式点击“开始同传”后发生;模拟链路不加载真实模型、不创建音频 Tap。