基于火山流式 ASR/TTS 的实时双工语音:回复朗读、打断、唤醒词、实时字幕、30 个中文音色与先响应后思考;在 DSH monorepo 内构建。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:tangzheng202202/dsh-voice-live
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
English | 中文
DSH 的实时语音交互:按下输入框麦克风即可说话,助手用语音朗读回答。本包分两半:
- 宿主侧:在 DSH 宿主进程内注册
/voiceWebSocket 升级路由。一个连接承载一个会话:麦克风 PCM 送入火山流式 ASR(bigmodel_async + 服务端 VAD 断句),助手回复文本送入火山流式 TTS(seed-tts-2.0)。升级先过 loopback-Host + 同源栅栏;宿主有connection.admit时再过 dsh 鉴权。每个异步操作有唯一生命周期所有者,音频走有界队列,TTS 为单一串行 worker。 - 客户端侧:渲染输入框麦克风控件(
conversation.input.left)与语音设置区(settings.section)。每个会话独享的VoiceController状态机拥有全部资源——AudioCapture(MediaStream/AudioContext/AudioWorklet)、VoiceTransport(WebSocket)、PlaybackQueue(播放)——并按代次拒绝迟到/旧消息。
API Key 由宿主的 process.env.VOLCENGINE_API_KEY 提供;浏览器不持有、不传输任何 Key。/voice 要求 loopback Host 和同源 Origin,然后再走 ctx.connection.admit()(用 ctx.inject(['connection']) 拿到,和其他插件一样)。拿不到 admit,或浏览器未登录,握手是 HTTP 401。本插件只读 operator 的 id、ctx、scope。ready 里 hasKey 不是 true 时,麦克风按钮会马上复位,并显示 后端未配置 VOLCENGINE_API_KEY。
安装(大约 5 分钟)
包名是 dsh-voice-live。官方 @deepseek-ai/dsh-* peer 接受已发布的 0.0.1-rc.5,或从 0.2.0-rc.2 起、不到 0.3.0 的 dsh 0.2.x(0.0.1-rc.5 || >=0.2.0-rc.2 <0.3.0-0)。dsh 是拿这个范围和自己的版本号比,所以把 peer 锁死成 0.0.1-rc.5 会在 0.2.0-rc.2 上直接拒装。Cordis 仍是 ^4.0.1。本仓库的开发安装和 npm test 继续用 0.0.1-rc.5,这一组能装上,也不会拉到没发布的 @deepseek-ai/dsh-compact。@deepseek-ai/dsh-client-runtime 没有 0.2.0-rc.2 这个版本;该版本的网页客户端仍使用同一套 ctx.slots.inject / ctx.slots.register。
使用 DeepSeek Harness
0.2.0-rc.2(或 peer 范围内的其它0.2.x),或者已经带有0.0.1-rc.5包的 Harness。把 Key 放在宿主上。变量名见
examples/api-key.env.example,写进~/.dsh/api-key.env(值留在你自己的机器上):VOLCENGINE_API_KEY=你的密钥安装并重启网页端:
dsh plugin --profile web add github:tangzheng202202/dsh-voice-live从 GitHub 安装时会跑构建。本仓库的
npm run build只用esbuild和tsc,不需要再克隆一份 DSH monorepo。打开对话,允许麦克风,点输入框左边的麦克风。说完停大约 1.5 秒,这句话会自己发出去。你应该先听到「好的,我去查一下。」,再听到正式回答。宿主没配 Key 时,按钮会提示
后端未配置 VOLCENGINE_API_KEY。
截图和 GIF 预定放在 assets/(文件还没放进来):
改这个仓库:npm install,然后 npm test,然后 npm run build。许可证是 MIT。
交互模型
- 点麦克风开始。激活时按钮显示科技感圆球与扩散波纹;识别文本增量进入输入框草稿。
- 句界由服务端判定:静音约 1.5 秒后自动产出 definite final 并提交,无需按停止。
stop()仍是"发送结束并等待最终结果",cancel()直接丢弃。 - 提交后连接进入应答模式保持打开:助手流式回复逐句合成,只在收到其
tts_done完整事件后播放。开启先响应后思考(默认开)时,语音会先回一句"好的,我去查一下。",再排队朗读正式回复。 - 回复朗读中再次说话会打断:停止播放 → 取消 TTS → 通过 DSH agents 服务取消在途 agent 回合 → 使旧消息 ID 失效 → 开始新一轮识别。
- 收听中连接断开自动重连(单重连器、指数退避、最多 5 次)。
设置
语音设置区可挑选音色(30 个实测可用的火山音色)、试听、切换"先响应后思考"。试听走同一 /voice 路由,由完成事件驱动(无固定 sleep)。
协议(浏览器 ↔ 宿主,单 WebSocket)
- 浏览器 → 宿主:二进制 = 16kHz Int16 单声道麦克风 PCM;控制帧
config(provider/voice/dshSessionId)、asr_start、asr_end、asr_cancel、tts_push、tts_flush、tts_cancel。 - 宿主 → 浏览器:
ready、asr_partial/asr_final(带 voiceSessionId、utteranceId、sequence)、tts_start+ 二进制音频 +tts_done、tts_error、tts_idle、error。 - 携带
voiceSessionId的控制帧必须属于本会话;超大帧与畸形 JSON 直接丢弃;伪造 Host 返回 403。
Model Experience
Voice path
What the model sees
无:麦克风流送往火山 ASR、助手回复文本送往火山 TTS(经宿主 /voice 路由),两类请求都不组装、追加或改写任何 LLM 提示词(助手回合是 DSH 普通 agent 循环)。
Token effect
无:本包不组装也不发送任何模型请求,故不计 token;任何计量完全属于服务该提示词的 agent 循环。
KV Cache effect
无;本包既不组装也不发送任何 provider 请求。
Known Limitations and Deferred Work
- 唤醒词以 Web Speech API 实现(Chrome/Safari、zh-CN、识别文本包含唤醒词即触发),默认关闭(持续占用麦克风)。两个约束如实记录、不遮掩:
- Chrome 的 Web Speech 识别走 Google 云端识别服务,国内网络不可达——设置里的「检测唤醒可用性」探针会显示具体
onerror原因(如network),不再静默失败;macOS 上可用浏览器是 Safari(Apple 服务)。 - 首选本地离线引擎 sherpa-onnx WASM 关键词检测被上游阻断:
sherpa-onnx-wasmnpm 包已删除(npm/jsdelivr/unpkg/npmmirror 均 404),当前 GitHub release 资产均为专用构建、wasm 内无 KWS 内核(已核实无sherpa_onnx_*_kws符号)。vosk-browser 作为备选评估过,但其固定中文词表无法约束「小戴」这类自定义词。WakeWordDetector接口保留未来本地 WASM 引擎的接入缝(待有可用分发)。
- Chrome 的 Web Speech 识别走 Google 云端识别服务,国内网络不可达——设置里的「检测唤醒可用性」探针会显示具体
- 回声消除依赖浏览器对 WebRTC 麦克风轨的 AEC(Chrome AEC3)。
VoiceController.getMicAec()可读取浏览器实际采纳值。new Audio()播放不在 Chrome AEC 覆盖内(Chromium bug 687574),因此循环保持半双工:TTS 播放期间门控麦克风帧,打断先停播放再开始新识别。受控回声测试(扬声器 vs 耳机、AEC 开关)步骤见交付说明;运行时决策为半双工 + 打断。 - 实时字幕以输入框增量草稿呈现(asr_partial);暂无悬浮字幕层。
- 服务端断句依赖火山优化双向流式端点(
bigmodel_async+enable_nonstream);普通bigmodel流只回 partial、不会自行结束。 - 本包
*.host.spec.ts在本仓库用npm test(vitest)运行,宿主半部经npm run build里的tsc -b出类型。 - 源码从 DSH monorepo 的
packages/client/ui-voice-live抽出。LICENSE 里的版权人仍是 DeepSeek。
链接
同类插件
Yuuyuko-uu/dsh-tts-bridge★ 254
用 DeepSeek 网页端自带的朗读,把 DSH 里的对话念出来,靠一个小浏览器扩展驱动。
Fishsb/dsh-voice-prompt-enhancer★ 127
把输入框草稿改写为更清晰、结构化的提示词(5 模式·模型回退链·可选多轮记忆),并为 DSH 语音输入加上说完自动停、热键与口水词清理;识别仍由官方 speechToText 提供,插件不自带引擎。
PolinniZhong/dsh-omi-voice★ 75
DeepSeek Harness 对话内朗读:点一下即可朗读、暂停、继续 AI 回复,豆包 TTS 自然音色(BYOK),只读最终回答并过滤代码、表格与图形,本地引擎,插件零 Key。
ppy-web/dsh-plugin-xiaomi-mimo-tts★ 58
为 DSH 提供小米 MiMo、豆包、Breeze 和浏览器语音,支持接入外部供应商与本地模型、文本过滤、实时流式朗读、音频下载、音效、桌宠及 QQ Bot、AI Passport 联动。
1624318455/dsh-plugin-tts★ 57
用免费 Edge TTS 或你自己的 RVC 音色朗读 AI 回复:消息朗读与自动朗读、长文自适应分块渐进播放(无缝衔接)、音色包仓库一键安装、便携 RVC 运行时。
beiyege-01/dsh-voice-ai-girlfriend-plugin★ 55
Web UI 语音 AI 女友:FunASR 麦克风语音输入、Qwen3-TTS 语音回复、数字人动画窗、QQ 双向聊天(文本/语音/图片推送,经 NapCat)。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。