DeepSeek Harness 插件

tangzheng202202/dsh-voice-live

Star 数 ★ 0 分类 语音与音频 收录于 2026-08-17

基于火山流式 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 宿主进程内注册 /voice WebSocket 升级路由。一个连接承载一个会话:麦克风 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。

  1. 使用 DeepSeek Harness 0.2.0-rc.2(或 peer 范围内的其它 0.2.x),或者已经带有 0.0.1-rc.5 包的 Harness。

  2. 把 Key 放在宿主上。变量名见 examples/api-key.env.example,写进 ~/.dsh/api-key.env(值留在你自己的机器上):

    VOLCENGINE_API_KEY=你的密钥
    
  3. 安装并重启网页端:

    dsh plugin --profile web add github:tangzheng202202/dsh-voice-live
    

    从 GitHub 安装时会跑构建。本仓库的 npm run build 只用 esbuild 和 tsc,不需要再克隆一份 DSH monorepo。

  4. 打开对话,允许麦克风,点输入框左边的麦克风。说完停大约 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-wasm npm 包已删除(npm/jsdelivr/unpkg/npmmirror 均 404),当前 GitHub release 资产均为专用构建、wasm 内无 KWS 内核(已核实无 sherpa_onnx_*_kws 符号)。vosk-browser 作为备选评估过,但其固定中文词表无法约束「小戴」这类自定义词。WakeWordDetector 接口保留未来本地 WASM 引擎的接入缝(待有可用分发)。
  • 回声消除依赖浏览器对 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。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。