DeepSeek Harness Web UI 全双工语音对话:按钮或 Ctrl+Shift+V 进入,持续聆听(停顿自动发送)或按住说话,zipformer2 流式识别入可编辑草稿、可选唤醒词;回复按句 Edge TTS 朗读并显示实时字幕,开口即打断播放与回合(真 barge-in);识别模型本地推理、Edge TTS 在线合成,无需 API Key。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-voice-mode
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:qishuilalala/dsh-voice-mode#path:/plugin/dsh-voice-mode
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。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
DeepSeek Harness 语音双工对话模式:会话内一键进入 → 边说边出字的流式识别 → 停顿自动发送 → 最终答复按句流式朗读 + 实时字幕,开口即可打断(真 barge-in)。无需 API Key,识别模型在本地宿主端推理。
中文 · English
Full-duplex voice mode for DeepSeek Harness — streamed ASR to an editable draft, sentence-by-sentence read-aloud with live captions, and speaking interrupts playback and the running turn.



运行时变更(最近一批:v0.7.17 ~ v0.7.19,2026-10-02):① 设置面全版本打通——dsh 0.1.7+ 上设置页与持久化修复(Settings → 语音模式 专属页、写入与重启保留);② 国际化重做——界面语言跟随 dsh 官方语言设置,中/英文完整一致、切换无需刷新;③ 修复 npm/pnpm 全新安装失败与 dsh ≥0.1.7 已安装形态「failed to import」(0.7.17 及更早版本受影响,请升级到 ≥0.7.18);④ 官方桌面端(Electron)下本地 Kokoro 修复——需系统 PATH 上有 Node.js ≥18(见下文「桌面端提示」)。此前批次(v0.7.10:输出链路静默丢音根治等)与完整历史见
CHANGELOG.md。
🤝 Fork 增强(本仓库新增)
本仓库在上游 haoku123/dsh-voice 基础上加入了大量增强,核心如下(完整清单见 git 历史与 docs/rules/STATE.md):
- 朗读默认 Edge 云端;本地 TTS 可选(隐私优先):选本地则回复文本不出本机——
- 本地 VITS(
sherpa-onnx-vits-zh-ll,纯中文,5 说话人); - 本地 Kokoro(中英混读,103 音色;
int8默认约 109MB / 可选fp32约 311MB 音质更好),经sherpa-onnx-node原生 addon 运行(无 WASM 内存上限,连续合成不崩); - Edge 云端朗读保留为可选(设置
ttsEngine: edge);设置面板「朗读引擎」热切换。
- 本地 VITS(
- Kokoro 音色全量 103 个(F0 实测标定性别),四个常用男声置顶带编号;音色面板用 下拉列表 + ◀▶ 步进切换;
- 增量传输:partial 只传新增 0.9 秒,长段按住说话松手秒出定稿(不再整段重传重解码);
- 交互增强:输入框旁模式切换按钮(持续聆听 ⇄ 按住说话,保存到设置);按住说模式下按住才录、不按住不打断;
- 长段支持:持续聆听连续多段自动拼成一条消息(内部按 30s 分块识别,跨块累积拼接),静音断句默认 1500 毫秒;按住说停顿不断句;
- 朗读稳定性:打断即终止在途合成释放 CPU;句间不再有 3-5 秒停顿;长朗读不触发空闲下线;
- 安全加固:会话存在性校验 / 回环+Origin 校验 / 全端点限流 / ASR+TTS 全模型 SHA256 固定 / 下载域名白名单 / 重定向守卫。
ℹ️ 顶部
demo-voice-flow.gif是当前界面的真实录制(语音模式 → 边说边出字 → 停顿自动发送 → 按句朗读 + 实时字幕),由screenshots/scripts/capture-demo.mjs驱动真实链路产出。
✨ 功能
- 语音模式:输入框工具排麦克风按钮或全局快捷键
Ctrl+Shift+V进入/退出;全局单活(同一时刻仅一个会话处于语音模式,切换会话自动让出) - 两种交互模式(输入框旁按钮或设置可切换,切换即持久化):
toggle(默认)持续聆听:RMS VAD 分段 → zipformer2 流式识别(边说边出字,实时字幕预览)→ 静音约 1500 毫秒断句进草稿,连续多段拼成一条消息,再静音约 1500 毫秒(合计约 3 秒)自动发送;按住Ctrl强制立即发送hold按住说话:短按进入/退出,按住麦克风按钮说话、松手即发(滑出取消、Esc/失焦放弃本段);按住期间停顿不断句(上限 10 分钟);Ctrl按住即录、松开即发
- 唤醒词(可选,默认关):设置
wakeWord后进入待机态,说出唤醒词才开始识别(如「你好小D」)。可直接与命令连说(「你好小D,帮我查天气」)——唤醒词会在定稿/字幕里自动剥掉、不进消息;匹配带容错(同音字替换「小莫→小墨」、首字错、前置语气词「呃/喂/我说」),建议 3-4 字;待机态状态条实时显示「说『x』开始 · 它听到的转写」,唤醒成败可自查。边界(重要):仅toggle模式生效(hold/ 手动打断下唤醒词静默失效);说完整一句后回到待机态需重说唤醒词(只喊唤醒词、还没说命令时保持聆听,可停顿想好再说);朗读期说唤醒词不触发(打断由 VAD 开口即触发,与唤醒词无关) - 字幕档位(批 3):
captionFontSize4 档(0=12px / 1=14px / 2=18px / 3=24px)+captionMaxWidth3 档(0=50vw / 1=70vw / 2=90vw),窄屏自适应 - 让位语义(批 5 / ADR-0008):
backchannelYield默认开(I10 豁免)—— 朗读期用户插话「嗯/对」自动让位 1.5s,真要说走硬打断;让 LLM 主动让出话轮(人格层让位);关掉恢复改造前行为 - 输出链路:只朗读最终答复的
text-delta(reasoning/工具调用不读),按句流式朗读(默认 Edge 云端;可切本地 VITS/Kokoro,中英混读选 Kokoro)+ 右下角实时字幕浮层;工具调用触发提示音;全文照常写入聊天记录;口语化提示词(设置spokenFormat,默认开)让回复为自然短句、不带 Markdown 排版符号 - 开口打断(barge-in):服务端 Silero VAD 帧级检测 + 回声门控(echoGateDb)三档灵敏度 → 本地静音 + host 合成队列作废 + 正在运行的回合取消(保留半截并自然续入新消息);朗读中自动切超灵敏档。开启唤醒词后打断仍是开口即打断(打断门控是 VAD,不是唤醒词;打断后回待机态)
- 模型懒加载与进度:首次使用自动下载识别/合成模型(
.part断点续传),状态条实时显示进度;可用npm run prefetch预下载 - 设置:入口随 dsh 版本而不同(见下方「设置」),可调朗读引擎/音色/语速/打断灵敏度/静音停顿/空闲超时/模型镜像/自动发送/交互模式/唤醒词/口语化提示词/字幕档位/让位语义;音色可试听(按当前音色+语速即时合成预览,自定义 ShortName 亦可)
- 界面语言:跟随 dsh 的语言设置(设置 → 通用 → 语言),切换即时生效、无需刷新——设置页、语音状态条、字幕、音色名称/性别/口音、错误提示全部随之变化;LLM 口语化提示词也按界面语言选中/英文版。插件词典注册在 dsh 官方 locale 服务的
voice-mode命名空间,社区语言包可据此补充其它语言,缺失的语言回落英文。插件名称与描述在「插件」页同样按语言显示。 - 容错:麦克风被拒红点提示、模型下载失败可见提示、TTS 连接失败状态条提示(自动退避重试)、提交失败文字留在草稿、SSE 断线自动重连
- 空闲退出:5 分钟无活动自动退出并释放麦克风(正在朗读计为活动,长朗读不会中途下线;批 J 已微调默认 10→5)
🚀 5 分钟上手(Quick Start)
dsh plugin --profile web add dsh-voice-mode
bundle 插件安装后需重启 dsh 生效(Linux:systemctl restart dsh;其他平台重启 dsh 进程)。
第一次用:
- 进入任一会话,按
Ctrl+Shift+V(或点输入区麦克风按钮)进入语音模式,状态条显示「聆听中…」; - 说一句完整的话(如「帮我看看今天的天气」)→ 实时字幕立即出现,停顿后自动发送;
- AI 回复开始朗读时,开口说话 → 朗读即刻停止,你的话被听见(这就是 barge-in)。
⌨️ 操作手势
| 手势 | 作用 |
|---|---|
Ctrl+Shift+V |
进入 / 退出语音模式 |
| 直接说话 | toggle:边说边出字,停顿约 1500 毫秒断句进草稿、再静音约 1500 毫秒(合计约 3 秒)自动发送;按住 Ctrl 强制立即发送 |
| 按住麦克风按钮 | hold:松手发送;短按退出;滑出 / Esc / 失焦放弃本段 |
| 点输入框旁模式按钮 | 在「持续聆听 ⇄ 按住说」间切换(保存到设置) |
| 说唤醒词 | 待机态激活识别(配置后) |
| AI 朗读时开口说话 | 打断朗读并取消当前回合 |
| 点状态条「退出」 | 退出语音模式 |
| 点字幕浮层「跳过」 | 跳过当前句朗读 |
⚙️ 设置
所有 dsh 版本通用入口:设置(Settings)→ 语音模式(Voice Mode)。另有按版本不同的次要入口(卡片内容一致):
- dsh ≤ 0.1.5:设置 → Plugins → 插件配置 → 语音模式
- dsh 0.1.6-alpha 及以后(含 0.1.7、0.2.0):左侧 Plugins → 已安装的
dsh-voice-mode→ 详情页「语音模式」卡片 - dsh 0.1.7+ 起,设置保存在插件自有文件
~/.dsh/voice-mode.settings.json($DSH_HOME下),优先于 profile 配置里的同名键;首次运行会从旧settings.yaml(.imported)的voice-mode:段迁移一次;恢复默认请把该文件内容改成{}(不要删除)。
| 键 | 默认 | 说明 |
|---|---|---|
ttsEngine |
edge |
朗读引擎:edge 微软云端(默认,快)/ vits 本地中文 / kokoro 本地中英;即时生效 |
kokoroModel |
int8 |
Kokoro 模型精度:int8(默认,109MB,纯 CPU/低带宽推荐)/ fp32(311MB,音质更好,独显/大内存推荐);两档共用 103 音色,即时生效 |
voice |
按引擎 | 音色:VITS 五说话人;Kokoro 103 个(下拉+◀▶,62 深沉/68 浑厚/75 清亮/76 磁性置顶);Edge 进入时自动加载全量 322 个。行内「试听」可即时预览 |
rate |
1.1 |
朗读语速倍率(0.5 慢速 ~ 2.0 快速),即时生效(批 J 1.0→1.1) |
interruptLevel |
0 |
发声打断灵敏度(服务端 VAD 帧级检测 + 回声门控):0 高门槛(3 帧)/ 1 中(2 帧)/ 2 低(1 帧) |
bargeInMode |
detect |
打断方式:detect 自动探测本机原生回声消除状态(默认;未生效时切为长按打断)/ auto 强制开口即打断(耳机、安静环境推荐)/ manual 长按打断(外放推荐)。批 7O 默认,I10 豁免(ADR-0006) |
echoGateDb |
6 |
回声门控阈值(dB):自动打断要求残差高于回声地板此值。原生 AEC 生效时此门控闲置(Safari / 耳机等无原生 AEC 环境才兜底生效);打不断降 3-4,噪音误打断升 8-10。不要为「打不断」调它(详见 ADR-0006) |
silenceMs |
1500 |
说完整一句的静音停顿毫秒数 |
idleTimeoutMinutes |
5 |
无活动自动退出语音模式的分钟数(朗读计为活动;批 J 10→5) |
modelHost |
默认源 | 模型下载源(国内网络填 https://hf-mirror.com) |
autoSend |
true |
静音到点自动发送(连续多段拼成一条消息);关闭则只进草稿(按住 Ctrl / hold 松手仍会发送) |
autoResume |
false |
切回上次语音会话时自动恢复语音模式(默认关)。开启后:下次进入语音会话即自动进入语音模式 + 恢复上次会话;关闭则需手动按 Ctrl+Shift+V 重新进入 |
mode |
toggle |
交互模式:toggle 持续聆听 + 1500ms 静音断句;hold 按住说话、松手发送(短按退出) |
shortcut |
Ctrl+Shift+V |
进入 / 退出语音模式的快捷键(修饰键 Ctrl/Shift/Alt/Meta + 一个字母键);留空 = 禁用快捷键,改用麦克风按钮 |
wakeWord |
空(关) | 唤醒词(如「你好小D」):进入后先说唤醒词激活,避免误触;空 = 关闭。可与命令连说,词头自动剥掉不进消息;匹配带容错(编辑距离 ≤1 + 前 3 字符前导窗口,吸收同音字/语气词);建议 3-4 字——单字词无容错、2 字词的容错会连带吸收所有同首字的 2 字词(如「小莫」也会唤醒「小张」),介意误唤醒用 3 字以上;每句断句或打断后回待机需重说;仅 toggle 模式生效(hold / 手动打断下不生效);朗读期说唤醒词不触发 |
toolBeep |
false |
工具调用提示音(默认关):开启后 AI 调用工具时「滴」一声;关闭则全程静默 |
spokenFormat |
true |
语音会话注入口语化提示词:开启后仅当前语音会话的回复被注入「口语化短句、不用 Markdown 排版符号」提示词(朗读更顺),即时生效 |
senseITN |
true |
批 2 P0:SenseVoice 逆文本归一化(数字/日期/货币规范化;默认开) |
senseVoice |
true |
定稿是否用 SenseVoice 重译(带标点 + 数字归一化,更准;默认开)。关闭可省 ~228MB 模型,只走流式识别(更快、精度下降) |
captionFontSize |
0 |
批 3 P0:字幕字号档位 0=12px / 1=14px / 2=18px / 3=24px(默认 0 与现状字节等价) |
captionMaxWidth |
1 |
批 3 P0:字幕宽度档位 0=50vw / 1=70vw / 2=90vw(视口 <686px 接近 480px,>686px 宽于 480px) |
backchannelYield |
true |
批 5 P1:让位语义(ADR-0008);朗读期说「嗯/对」自动让位 1.5s + 真要说走硬打断。I10 豁免(默认开是产品决策);关 = 行为等同改造前 |
yieldMs |
1500 |
让位窗口时长(ms,500-3000):backchannelYield 命中后 TTS 丢帧持续时长;窗口内用户真要说则由原 hardBreak 接管,窗口到点自动恢复播放 |
生效范围:voice/rate/ttsEngine/kokoroModel/spokenFormat 立即生效;其余设置下次进入语音模式时生效。设置项默认值由插件配置(base 层)提供。
本地音色(VITS / Kokoro)
桌面端(Electron)提示:官方桌面端的宿主运行在 Electron 里,其 V8 不允许 Kokoro 的原生 addon 返回外部缓冲区。插件会自动改用一个真正的 Node.js 来跑 Kokoro——需要系统 PATH 上有 Node.js ≥18(或用环境变量
DSHVM_NODE指定路径);没有则 Kokoro 会提示失败,请改用默认的 Edge 或本地 VITS(两者在桌面端不受影响)。
- VITS(纯中文):
suyingxue素映雪·女 /gunian顾念·男 /fushiyu傅斯遇·女 /bingjiao冰娇·男 /bazong霸总·男 - Kokoro(中英混读均可):103 个音色全量入表,面板按编号 + 实测性别标注;四个常用男声置顶:
62深沉 /68浑厚 /75清亮 /76磁性;中文女声48小北 /49小妮 /50小小 /51小艺。音色只是风格向量,语言能力与音色无关。
常用 Edge 音色(完整清单见 node scripts/list-voices.mjs)
| ShortName | 说明 |
|---|---|
zh-CN-XiaoxiaoNeural |
晓晓 · 女声(默认) |
zh-CN-XiaoyiNeural |
晓伊 · 女声 |
zh-CN-YunxiNeural |
云希 · 男声 |
zh-CN-YunjianNeural |
云健 · 男声 |
zh-CN-YunyangNeural |
云扬 · 男声 |
zh-CN-YunxiaNeural |
云夏 · 男声 |
zh-CN-liaoning-XiaobeiNeural |
小北 · 东北话 · 女声 |
zh-HK-HiuMaanNeural |
晓曼 · 粤语 · 女声 |
zh-TW-HsiaoYuNeural |
小雨 · 台湾腔 · 女声 |
en-US-AriaNeural |
Aria · English · 女声 |
🔧 配置(bundle patch / settings.yaml)
也可以直接编辑 ~/.dsh/settings.yaml 的 voice-mode: 段(设置面板与 RPC 写的是同一份文档层):
- id: voice-mode
name: dsh-voice-mode
config:
enabled: true # false = 完全禁用语音模式(toggle 会被拒)
cacheDir: ~/.cache/dsh-voice-mode/models # 可覆盖;否则用平台默认
# 以下为设置项播种的默认值(设置面板优先级更高,面板是权威源):
voice: zh-CN-XiaoxiaoNeural
rate: 1.1 # 批 J 1.0→1.1
interruptLevel: 0
silenceMs: 1500
idleTimeoutMinutes: 5 # 批 J 10→5
modelHost: https://huggingface.co
注意:
voice/rate/interruptLevel/silenceMs/idleTimeoutMinutes/modelHost/autoSend的生效值来自设置面板;bundle 配置只负责为这些键播种默认值 (enabled/cacheDir则仅由 bundle 配置决定)。 插件 HTTP 命名空间固定为/voice-mode(与客户端打包契约一致,不可配置)。
🌐 API
| 路由 | 说明 |
|---|---|
GET /voice-mode/stream |
SSE:event: audio({sessionId, seq, text, audio(base64 MP3)})、event: mode(全局单活归属)、event: tool(提示音)、event: asr-progress / asr-ready / asr-error / tts-error |
POST /voice-mode/toggle |
{sessionId, on} 进入 / 退出语音模式(全局单活) |
POST /voice-mode/asr |
裸 f32 LE 16k PCM → {text}(流式 zipformer2);模型未就绪返回 202 {loading};?reset=1 丢弃在途段(唤醒词命中时使用) |
POST /voice-mode/cancel |
{sessionId} 作废 TTS 队列并丢弃在途 ASR 段 |
POST /voice-mode/preview |
{voice, rate?} 一次性合成试听 → audio/mpeg(400 缺 voice / voice 过长;502 合成失败,如无效 ShortName;403 插件 enabled=false)。不要求语音模式处于激活态;使用独立合成连接,不影响朗读队列 |
GET /voice-mode/config |
客户端启动参数(静音阈值 / 灵敏度 / 音色与语速等)——含 ASR 侧字段 senseITN / senseVoice / captionFontSize / captionMaxWidth / backchannelYield |
GET /voice-mode |
健康检查 {ok, name, enabled, active} |
💾 模型与缓存
- 识别模型:
csukuangfj/sherpa-onnx-streaming-zipformer-zh-int8-2025-06-30(encoder ≈154 MB / decoder / joiner / tokens,合计约 160 MB),宿主端经 sherpa-onnx(Node WASM,Apache-2.0,原生跨平台)运行 - 缓存目录的平台默认:
- Windows:
%LOCALAPPDATA%\dsh-voice-mode\models - macOS / Linux:
~/.cache/dsh-voice-mode/models - 两者都可用
cacheDir覆盖
- Windows:
- 下载用
.part断点续传;huggingface.co失败时回退hf-mirror.com(可用modelHost配置)
🏛️ 工作原理(Architecture)
flowchart LR
subgraph Client[浏览器 Client]
Mic[麦克风 16kHz<br/>AudioWorklet<br/>echoCancellation:true] --> VAD[客户端 VAD<br/>RMS 分段]
VAD -->|partial 0.9s| UI[状态条 + 字幕浮层]
end
subgraph Host[宿主 dsh.host]
ASR[zipformer2 流式识别<br/>host 端 WASM]
SV[SenseVoice 定稿<br/>+ ITN + 标点]
Tap[llm/stream tap<br/>仅观察·不阻塞]
Seg[sentence segmenter]
Q[TtsQueue<br/>epoch 打断]
TTS{引擎}
Edge[Edge 云端]
Vits[本地 VITS WASM]
Kokoro[本地 Kokoro<br/>原生 addon]
end
UI -->|audio f32 PCM<br/>POST /voice-mode/asr| ASR
ASR --> SV
SV --> Draft[composer draft<br/>autoSend]
Draft --> Tap
Tap --> Seg
Seg --> Q
Q --> TTS
TTS -->|edge| Edge
TTS -->|vits| Vits
TTS -->|kokoro| Kokoro
Edge -.->|SSE audio frame| UI
Vits -.->|SSE audio frame| UI
Kokoro -.->|SSE audio frame| UI
VAD -.->|唤醒词/打断| Q
- 识别在 host 端本地运行(zipformer2 中文 int8 WASM + SenseVoice 定稿,模型懒下载),音频不上传第三方;识别定稿由 SenseVoice 补标点;
- 朗读默认 Edge 云端;本地 VITS 纯中文 / Kokoro 原生中英(跑在独立子进程、崩溃自愈)可选(隐私优先);
- 同一时间仅一个会话处于语音模式(全局单活);LLM 流被无损观察(不阻塞)。
详细架构决策:见 docs/adr/ 8 个 ADR。
🔍 与 dsh 内置语音模式对比
| 维度 | dsh 内置 | dsh-voice-mode(本插件) |
|---|---|---|
| 识别模型 | 云端 API(需 key) | 本地 zipformer2 + SenseVoice(零 key) |
| 多语种 | 英文为主 | SenseVoice 自动识别(zh/en/ja/ko/yue)+ ITN |
| 朗读引擎 | 云端 TTS | Edge 云端 + 本地 VITS/Kokoro 三选一 |
| 打断检测 | 基础 VAD | 三档灵敏度 + 回声门控 + 让位语义 |
| 热词偏置 | 无 | 无(已移除,详见 v0.7.7 文档说明) |
| 字幕 a11y | 无 | 4 档字号 + 3 档宽度 + 主题跟随 |
| 唤醒词 | 无 | 轻量流式匹配 + 前缀语气词白名单 |
| 兼容 dsh | — | 0.1.1-rc.2 起全版本(含 0.2.1-alpha.1) |
🔐 权限与数据流声明
插件如实声明它会做的事(与 awesome-dsh-plugin 的能力扫描 network / fs-read / fs-write / shell / env 一一对应):
| 类别 | 具体行为 | 数据去向 |
|---|---|---|
| network | ① 默认朗读引擎 Edge:把待朗读的回复文本经 WebSocket 发给微软 speech.platform.bing.com(云端合成;想完全离线请切到本地 VITS / Kokoro);② 首次使用本地模型时从 huggingface.co(或你配置的镜像 hf-mirror.com)下载,主机白名单 + 固定 SHA256 校验;③ 在 dsh 宿主上注册回环 HTTP 路由 /voice-mode/*(默认仅回环,需 allowLan 才对局域网开放) |
麦克风音频不出本机(识别在本地 sherpa-onnx);仅回复文本在 Edge 引擎下发往微软 |
| fs-read / fs-write | 模型缓存(Linux/macOS ~/.cache/dsh-voice-mode/models/,Windows %LOCALAPPDATA%\dsh-voice-mode\models\);dsh 0.1.7+ 的设置覆盖层 $DSH_HOME/voice-mode.settings.json;不读写你的工作区文件 |
全部在本机 |
| shell(子进程) | 本地 TTS 合成跑在独立子进程(child_process.fork → lib/tts-vits-worker.cjs);宿主为 Electron(官方桌面端)时,为 Kokoro 额外探测并启动一个真正的 Node.js(node -p … 探测版本,见 ADR/兼容契约)。不执行用户输入、不经 shell 拼接命令 |
本机 |
| env | 仅读取 DSH_HOME、LOCALAPPDATA(取目录)与可选的 DSHVM_NODE;不读取、不需要任何 API Key |
— |
补充:调试用的真机录制(fixture)默认关闭;插件不上传遥测。完整威胁模型与漏洞报告方式见仓库根目录 SECURITY.md。
第三方模型与服务说明
- 本地模型不随包分发:ASR(zipformer 流式、SenseVoice 重译)、VAD、本地 TTS(VITS / Kokoro)的模型由插件首次使用时从 Hugging Face(或你配置的镜像)下载到本机缓存,来源为 sherpa-onnx 生态的导出仓库(
csukuangfj/*)。各模型的许可由其原作者决定,本插件的 MIT 许可不覆盖这些模型;用于商业场景前请自行核对上游许可(模型清单见下文「模型与缓存」,对应常量在src/asr-host.ts/src/tts-local.ts)。 - Edge 云端朗读是第三方在线服务:默认引擎经
msedge-tts使用微软 Edge 浏览器「大声朗读」的在线接口——这不是微软官方提供的稳定 API,可用性、速率与条款均由微软决定,可能随时变化。对稳定性/合规有要求的场景请改用本地 VITS / Kokoro(离线)。 - 被内联进发布包的第三方代码(
msedge-tts及其依赖)的许可见THIRD_PARTY_NOTICES.md;已用pnpm audit保证发布时无已知高危漏洞(CIauditjob 持续监测)。
兼容声明(插件市场的版本筛选依据)
package.json 声明 engines.dsh = ">=0.1.1-rc.2"(插件市场据此在「按宿主版本筛选」时判定兼容)。已实测范围 0.1.1-rc.2 → 0.2.1-alpha.1(含官方桌面端等价的 Electron 宿主);上限开放,由每周 CI 巡检上游新版本并复验,出现未覆盖版本会自动开 issue。peerDependencies 仅声明 @deepseek-ai/cordis 与 react(宿主提供)。
🚧 已知限制
- 发声打断依赖浏览器回声消除(
echoCancellation);扬声器音量过大时可能漏声到麦克风 Ctrl+Shift+V会覆盖浏览器「粘贴纯文本」快捷键(普通粘贴仍可用Ctrl+V)- 识别质量受环境噪声影响;zipformer2 中文流式 + SenseVoice 多语(中英日韩粤)定稿
- 浏览器自动播放策略:朗读需要页面已有用户交互(点击麦克风即满足);「试听」依赖
AbortSignal.timeout(Safari 16+ / Chrome 103+ / Firefox 100+;老浏览器点击试听会立即提示失败,属预期降级) - 唤醒词为轻量实现(流式文本匹配,非专用 KWS 引擎):嘈杂环境可能延迟或误激活;唤醒词本身不会进入聊天
- hold 模式按住时切换窗口/标签页会放弃本段(防持续收音)
- hero(新会话空态)无语音入口:请先进入会话使用麦克风按钮
spokenFormat提示词经官方system-prompt/assemble瀑布注入;若当前会话使用完整提示词配置(personacomplete: true的 agent preset),提示词不注入(官方 complete 契约优先)- 本地 Kokoro 每次打断后下一句朗读前约有 1 秒引擎重建时间(打断即终止在途合成的代价)
- 苹果 Safari / iOS:
- 需 HTTPS 或 localhost(iOS/macOS Safari 强制安全上下文;
http://局域网 IP 下麦克风不可用) - 首次进入需授权麦克风;被拒后到「设置 → Safari → 麦克风」开启(iOS)
- iOS 后台/锁屏时识别与朗读暂停,回前台自动恢复(可能丢句);建议语音模式期间保持前台
- 需 HTTPS 或 localhost(iOS/macOS Safari 强制安全上下文;
- 安全说明:插件 HTTP 面(
/voice-mode/*)遵循宿主安全模型——请勿将 dsh 端口直接暴露公网;经反向代理发布时由代理层(如 basic auth)鉴权;插件侧对敏感操作保留会话归属校验
🛠️ 故障排查
| 现象 | 处理 |
|---|---|
| 点麦克风无反应,状态条红字 | 浏览器拒绝麦克风:地址栏(iOS 为 设置 → Safari → 麦克风)开启后重试 |
| 状态条「正在加载模型… x%」卡住 | 检查网络;模型较大可先 npm run prefetch;国内网络 modelHost 配 https://hf-mirror.com |
| 朗读无声音/无字幕 | 本地引擎首次合成需加载模型;若持续失败查看状态条提示(自动退避重试);确认页面前台且未静音 |
| AI 回复偶尔不朗读(某句没声/整条没声) | 已定位三类原因并修(v0.7.10):① 云端 TTS 偶发超时——单句自动重试 3 次,仍失败会跳过该句并在状态条提示「有一句朗读失败,已跳过」(此前是静默丢句);② 浏览器挂起 AudioContext(切到后台标签页/长时间静音后回来)——播放被调度但无声、UI 却显示朗读中;现在每次入队与任意点击/按键都会自动恢复;③ SSE 断线丢帧导致整句不完整——按设计丢弃该句(避免播坏音频),可开 localStorage['dsh-voice-mode.telemetry']='1' 看 tts-drop-sentence 诊断 |
| 语音模式进不去 | 检查插件 enabled;多标签页时确认当前会话为活动会话 |
| 识别到但不是我要说的 | 环境噪声或唤醒词误判:降低音量、提高 interruptLevel(高门槛)或启用 wakeWord |
| 唤醒词唤不醒 | 先看待机态状态条的实时转写(它听到了什么):同音字 1 字内已自动容错;停顿约 1.5 秒(= 静音断句时长)再说,清掉待机段残留语音、从段首重新匹配;换一个转写稳定的词(建议 3-4 字) |
| 打断后说话没反应(开了唤醒词) | 唤醒词只管「开始识别」的门:打断/每句断句后回到待机态,需重说唤醒词再继续说;待机态状态条会显示「说『x』开始」提示 |
| 唤醒词完全没反应 | ① 确认交互模式是 toggle(hold 与手动打断下唤醒词不生效);② 确认 bargeInMode:manual(或 detect 在本机无原生回声消除时自动落 manual)会关闭常驻聆听 → 唤醒词失效,改回 auto 或按住麦克风/Ctrl;③ 朗读期说唤醒词不触发(先等 AI 说完);④ 看待机态实时转写,确认它听到了什么(同音字 1 字内已容错,建议 3-4 字词) |
| 按住说话松手后没反应 | 确认交互模式为「按住说」且按住期间按钮高亮;松手后识别定稿约 1 秒内进入草稿 |
| 打不断(朗读中开口无反应) | 调高 interruptLevel(更敏感档 = 0 或 1)或检查麦克风权限;若 VAD 持续不触发可临时切到「手动打断」(mode: hold / 唤醒词定时延后);不要调 echoGateDb——真机 3.1 分钟朗读期里 Silero 0/777 帧把回声判成语音,原生 AEC 生效时此阈值从未被执行(详见 ADR-0006) |
| 官方桌面端上选本地 Kokoro,设置里显示「加载失败」并提示需要 Node.js | 桌面端宿主是 Electron,Kokoro 的原生 addon 在其中不可用:在系统 PATH 上安装 Node.js ≥18(或设环境变量 DSHVM_NODE 指向它)后重试;或改用默认的 Edge / 本地 VITS(桌面端不受影响) |
| 字幕被输入框挡住 | 默认 captionMaxWidth=1(70vw)+ captionFontSize=0(12px)在窄屏可能与底部输入框重叠;调高档位或点字幕浮层「×」收起 |
| 让位行为异常(朗读期说「嗯」不停 / 真话被打断) | 「嗯/对」类短词触发让位 1.5s 后继续朗读;继续说真话会走硬打断;不要时关 backchannelYield 即可恢复改造前行为(ADR-0008) |
| 朗读期说「嗯」没让位 | 确认 backchannelYield=true(默认开);hold 模式松手后让位 1.5s 内继续说话会变硬打断 |
| 空闲 5 分钟自动退出(不想退) | 调高 idleTimeoutMinutes(默认 5 分钟,朗读计为活动) |
🛣️ 路线图(Roadmap)
完整 backlog(43 项 P0-P3)见 docs/competitive/backlog.md。
- ✅ 已完成(v0.7.7):11 批次周全修复(字幕档位 / 让位语义 / 模型预热 / 默认值微调 / 死代码清理等)
- 🚧 P0(近期):ADR-0003 VAD 下沉 / ADR-0006 第一级探测接通 manual / F1 emotion DSL 全量上线
- 📋 P1(中期):MCP
voice_*工具集 / 卡片表单 draft validate / 状态条 idle 优化 - 💡 P2(远期):声音克隆(用户已决定推迟)/ ADR-0004 WebSocket transport
- ⏸️ 已推迟:xAI fallback / C1 人格层(用户已决定推迟)
🛠️ 开发
pnpm install && pnpm build # esbuild:lib/index.js(host)+ lib/client.js(browser)
pnpm test # segmenter/wakeword 单测 + 发布前自检(无需网络)
systemctl restart dsh # 本机加载新 host 代码;其他平台重启 dsh 进程
注意:dsh 安装的是 pnpm
file:链接(目录拷贝),改完node build.mjs后需把lib/client.js同步到<profile>/node_modules/dsh-voice-mode/lib/再刷新页面(lib/index.js与工作区为同一文件自动同步)。集成探测脚本(test/hold-e2e.js、test/spoken-prompt-rpc.sh、test/spoken-toggle-ui-check.js)位于仓库根test/,不在 npm 包内。
src/index.ts host:单活指针、llm/stream tap、SSE、settings 注册、口语化提示词注入
src/asr-host.ts host:zipformer2 流式识别 + SenseVoice 定稿 + 模型懒下载(.part 断点续传)+ 增量喂料
src/models.ts host:模型下载/校验(SHA256 固定 + 域名白名单)
src/security.ts host:限流器与安全守卫
src/tts-local.ts host:本地 TTS 引擎(VITS WASM / Kokoro 原生 addon,子进程管理)
src/tts-vits-worker.ts 子进程:合成执行(base64 IPC,空文本静音守卫)
src/tts-queue.ts host:逐会话 TTS 队列 + epoch 打断机制
src/segmenter.ts host:句子切分 + 文本消毒(markdown 剥离 + 噪声字符剔除)
src/asr.ts client:音频采集、VAD 分段、增量识别、唤醒词、按住说门控
src/client.tsx client:麦克风按钮 + 模式切换按钮 + 状态条 + 字幕浮层 + 打断
src/strings.ts client:中英文案词典(zh / en 两份,键一一对应;有测试守卫)
src/i18n.ts client:接入官方 locale 服务(语言即时切换、语言包扩展、无服务时回退)
src/voice-catalog.ts host+client:音色目录单一数据源;src/voice-labels.ts 按语言生成音色/镜像标签
src/errors.ts host↔client:稳定错误码(host 不发自然语言,客户端按语言翻译)
src/prompts.ts host:LLM 口语化提示词(中/英)与试听例句(按音色语种)
📄 License
部分实现借鉴 haoku123/dsh-voice(派生声明见子包 LICENSE)。
链接
同类插件
PolinniZhong/dsh-omi-voice★ 74
DeepSeek Harness 对话内朗读:点一下即可朗读、暂停、继续 AI 回复,豆包 TTS 自然音色(BYOK),只读最终回答并过滤代码、表格与图形,本地引擎,插件零 Key。
PensiveFei/dsh-voice-scribe★ 35
面向 Web UI 的语音输入插件:点按 Alt(或 Alt+空格)开始/停止听写,支持浏览器内置 Web Speech(零配置)或 OpenAI 兼容云端 ASR,可选经 DSH 已配置模型润色,带设置页。
1624318455/dsh-plugin-tts★ 24
用免费 Edge TTS 或你自己的 RVC 音色朗读 AI 回复:消息朗读与自动朗读、长文自适应分块渐进播放(无缝衔接)、音色包仓库一键安装、便携 RVC 运行时。
WizisCool/dsh-ears★ 22
面向 DeepSeek Harness (dsh) 的语音输入插件:输入框的麦克风按钮把语音转成草稿文本,支持多种语音识别后端,可选经 dsh 自有 LLM 路由润色,并带原生设置页。
PerryLink/dsh-talk★ 17
DeepSeek Harness 的语音输入输出:麦克风语音转文字与文字转语音。
ppy-web/dsh-plugin-xiaomi-mimo-tts★ 15
为 DSH Web 添加 Xiaomi MiMo 语音朗读,支持助手消息朗读、PCM 流式播放、预置与自定义音色、浏览器语音兜底、播放控制和可选 UI 音效。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。