架构
OtterVoice 是语音会话编排 SDK,不是模型网关。Core 管状态、轮次、打断与用量;平台音频与模型通过接口注入。
Application UI ↕ events / commands@ottervoice/core VoiceSession · 状态机 · VAD · barge-in · usage ↕ RuntimeAdapter ↕ Gateway client providers(仅用户内容)runtime-web | rn | node 自有鉴权网关(服务端策略) ↕ Provider API 原生 Audio LLM 或服务端 ASR → LLM → TTS| 层 | 负责 | 不负责 |
|---|---|---|
| UI | 绑定事件、展示字幕、调 start / finish、本地 VAD/播放偏好 |
Provider 模型、系统提示词、声音、生成参数、长期密钥 |
| Core | 状态机、轮次、打断策略、用量、错误归一 | DOM / Expo / Node 特有 API |
| Runtime | 麦、播放、可选 network/storage | 业务提示词、模型选型 |
| Gateway client Provider | 只发送用户文本/音频、历史和流式传输标记 | 决定模型、prompt、voice、temperature、token 上限 |
| 自有服务端网关 | 用户/会话鉴权、策略注入、参数重建、配额和审计 | 信任浏览器传入的业务策略 |
| Direct Provider | 可信 Node/服务端内的云厂商协议 | 为不可信客户端提供授权边界 |
audioLlmSystemPrompt、LLMGenerateInput.system 等字段仍可用于完全在
可信 Node/服务端运行的 Session。浏览器或 App 的标准模式应省略这些字段,
改用 createOpenRouterGateway* 客户端工厂;服务端通过
createOpenRouterGateway() 注入模型、prompt、voice 和生成上限。
客户端仍可控制 VAD、字幕显示、播放、打断等体验参数。滚动 ASR、 提前发起 audio-turn 与自动重试会影响成本;若产品允许客户端选择后端, 网关必须按用户/会话/profile 另行执行预算和速率限制。
一个契约,两种后端
Section titled “一个契约,两种后端”- 原生后端:整轮音频进入原生 Audio LLM,直接返回助手文本与音频。
- 复合后端:同一个
AudioLLMProvider在可信服务端执行 ASR → LLM → TTS,并流式返回输入转写、助手文本与音频。
客户端始终配置 providers.audioLlm。复合 Provider 通常以
transcribesInput: true 返回同一请求中的输入转写,避免额外的字幕 ASR;原生
Provider 不返回输入转写时可再配置 providers.asr。audioLlmStartTiming 决定
独立字幕 ASR 与回复生成并行,还是等待 asr_final。
组合根创建 Session 一次,UI 只订阅事件。换 Runtime / Provider 不必改 UI。
本地轮次检测
Section titled “本地轮次检测”TurnDetector 只使用麦克风音量和确定性的时间规则。volume 在本地检测开始
说话与尾部静音;hybrid 还允许 ASR partial 确认较轻的语音,但仍由同一套本地
静音计时结束轮次;manual 则把轮次边界交给按键说话 UI。
Runtime 可以同时发送低延迟的 AudioChunk.delivery: 'stream' 分片,并在录音器
完全 flush 后发送一份不可变的 delivery: 'turn' 整轮快照。Core 用后者做 batch
ASR、Audio LLM 输入和 user_audio_final,避免流式 reset 或异步 Blob 读取造成
显示文本对应的音频头部、中间或尾部丢失。