dsh-voice-mode 0.7.16 → 0.7.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -3,14 +3,14 @@
3
3
  [![License: MIT](https://img.shields.io/github/license/qishuilalala/dsh-voice-mode?style=flat-square&color=blue)](../../LICENSE)
4
4
  [![Latest Release](https://img.shields.io/github/v/release/qishuilalala/dsh-voice-mode?style=flat-square&color=brightgreen&include_prereleases)](https://github.com/qishuilalala/dsh-voice-mode/releases)
5
5
  [![npm version](https://img.shields.io/npm/v/dsh-voice-mode?style=flat-square&color=orange)](https://www.npmjs.com/package/dsh-voice-mode)
6
- [![Tests: 380 passing](https://img.shields.io/badge/tests-380%20%E2%9C%93-2ea043?style=flat-square)](../../docs/rules/STATE.md)
6
+ [![Tests: 424 passing](https://img.shields.io/badge/tests-424%20%E2%9C%93-2ea043?style=flat-square)](../../docs/rules/STATE.md)
7
7
 
8
8
  Full-duplex voice conversation mode for DeepSeek Harness (dsh): speak, get a
9
9
  spoken answer. Streamed zipformer2 ASR → editable draft → auto send → the
10
10
  final reply is read out sentence-by-sentence via Edge TTS, and your voice
11
11
  interrupts playback and the running turn. No API key.
12
12
 
13
- > 中文说明见 [README.md](./README.md)。
13
+ > **English** · [中文](https://github.com/qishuilalala/dsh-voice-mode/blob/HEAD/plugin/dsh-voice-mode/README.md)
14
14
 
15
15
  ![dsh-voice-mode full-duplex voice conversation](https://raw.githubusercontent.com/qishuilalala/dsh-voice-mode/HEAD/assets/hero-banner.png)
16
16
 
@@ -46,7 +46,8 @@ interrupts playback and the running turn. No API key.
46
46
  - **Barge-in**: three sensitivity levels of voice-onset detection → local mute + host synth queue invalidation (epoch) + running turn cancellation (the half-finished part is kept and naturally flows into your new message). With a wake word set, barge-in **remains speak-to-interrupt** (the gate is the VAD, not the wake word; the engine returns to standby afterwards)
47
47
  - **Lazy model download with progress**: the zipformer2 Chinese streaming model (~160 MB, `.part` resumable) is downloaded on first use with live progress in the status bar; `npm run prefetch` can pre-download it
48
48
  - **Resilience**: mic-denied red hint, visible model-download failure, TTS unreachable status hint (auto retry), failed submit keeps the text in the draft, SSE auto-reconnect
49
- - **Settings**: Settings → Plugins → voice-mode, with voice / rate / interrupt sensitivity / silence pause / idle timeout / model mirror / auto send / interaction mode / wake word / ITN / caption tiers / yield semantics; **voices are previewable** (the "试听/Preview" button synthesizes and plays the current voice at the current rate instantly, no need to enter voice mode; custom ShortNames are previewable too)
49
+ - **Settings**: location depends on your dsh version (see Settings below), with voice / rate / interrupt sensitivity / silence pause / idle timeout / model mirror / auto send / interaction mode / wake word / ITN / caption tiers / yield semantics; **voices are previewable** (the "试听/Preview" button synthesizes and plays the current voice at the current rate instantly, no need to enter voice mode; custom ShortNames are previewable too)
50
+ - **Interface language**: follows dsh's language setting (Settings → General → Language) and **switches instantly, no reload** — the settings page, voice status bar, captions, voice names/gender/accent and error messages all follow it, and the LLM spoken-style prompt is chosen in English or Chinese accordingly. Dictionaries are registered in dsh's official locale service under the `voice-mode` namespace, so community language packs can add more languages (missing ones fall back to English). The plugin's name and description in the Plugins page are localized too.
50
51
  - **Idle exit**: auto-exit and mic release after 5 minutes of inactivity (reading counts as activity; batch J 10→5)
51
52
 
52
53
  ---
@@ -104,13 +105,20 @@ npm run prefetch # run inside the plugin dir; writes to the platform ca
104
105
  3. The AI answer is read sentence-by-sentence with a caption overlay at the bottom-right; click "Skip" or just start speaking to interrupt
105
106
  4. Click "Exit" in the status bar (or press `Ctrl+Shift+V` again) to leave voice mode
106
107
 
107
- On first entry the recognition model is downloaded; the status bar shows `正在加载模型… <file> <percent>%`.
108
+ On first entry the recognition model is downloaded; the status bar shows `Loading model… <file> <percent>%`.
108
109
 
109
- If a wake word is configured, you land in standby first (the status bar prompts `说『唤醒词』开始`), and recognizing starts after you speak the wake word.
110
+ If a wake word is configured, you land in standby first (the status bar prompts `Say "<wake word>" to start`), and recognizing starts after you speak the wake word.
110
111
 
111
112
  ---
112
113
 
113
- ## ⚙️ Settings (Settings → Plugins → Plugins config → 语音模式)
114
+ ## ⚙️ Settings
115
+
116
+ **Works on every dsh version: Settings → Voice Mode** (the plugin registers its own page in the Settings dialog). Secondary entry points (same card) vary by version:
117
+
118
+ - dsh ≤ 0.1.5: Settings → Plugins → plugin config → voice mode
119
+ - dsh 0.1.6-alpha and later (incl. 0.1.7 / 0.2.0): left sidebar **Plugins** → the installed `dsh-voice-mode` → the "Voice Mode" card on its detail page
120
+ - On dsh 0.1.7+ the values are stored in the plugin's own file `~/.dsh/voice-mode.settings.json` (under `$DSH_HOME`) and take precedence over same-named keys in the profile config. The first run migrates the old `voice-mode:` block from `settings.yaml(.imported)` once. To reset, set the file's content to `{}` (do not delete it).
121
+
114
122
 
115
123
  ### 4 new settings (11 batches of comprehensive fixes)
116
124
 
@@ -140,17 +148,24 @@ If a wake word is configured, you land in standby first (the status bar prompts
140
148
  | `voice` | per engine | Voice: 5 VITS speakers; 103 Kokoro voices (◀▶ stepper; 62/68/75/76 favourite males pinned); Edge ShortNames below. The inline "试听" button previews it at the current rate |
141
149
  | `rate` | `1.1` | Reading speed multiplier (0.5 slow ~ 2.0 fast), **applies live** (batch J 1.0→1.1) |
142
150
  | `interruptLevel` | `0` | Barge-in sensitivity (host-side VAD frame detection + echo gate): 0 high threshold (3 frames) / 1 medium (2 frames) / 2 low (1 frame) |
151
+ | `bargeInMode` | `detect` | Barge-in mode: `detect` auto-probes native echo cancellation (default; falls back to hold-to-talk when it is not in effect) / `auto` force interrupt as soon as you speak (headphones / quiet rooms) / `manual` hold-to-talk (recommended on loudspeakers). Batch 7O default, I10-exempt (ADR-0006) |
152
+ | `echoGateDb` | `6` | Echo-gate threshold (dB): auto barge-in requires the residual to exceed the echo floor by this much. **Idle while native AEC is in effect** (it only acts as a fallback on Safari / headsets without native AEC); lower by 3-4 if you cannot interrupt, raise by 8-10 if noise interrupts. **Do not tune it for "cannot interrupt"** (see ADR-0006) |
143
153
  | `silenceMs` | `1500` | Silence pause in ms that marks the end of a complete sentence |
144
154
  | `idleTimeoutMinutes` | `5` | Minutes of inactivity before auto-exiting voice mode (reading counts as activity; batch J 10→5) |
145
155
  | `modelHost` | default | Model download host (use `https://hf-mirror.com` on mainland networks) |
146
156
  | `autoSend` | `true` | Auto-send once quiet (consecutive segments join into one message); when off, text only goes to the draft (hold `Ctrl` / release in hold mode still sends) |
147
157
  | `mode` | `toggle` | Interaction mode: `toggle` continuous listening + 1500 ms silence split; `hold` push-to-talk, release to send (short tap exits) |
158
+ | `autoResume` | `false` | Auto-restore voice mode when switching back to your last voice session (off by default). When on: the next time you enter that session it auto-enters voice mode and restores it; when off, press `Ctrl+Shift+V` manually |
159
+ | `shortcut` | `Ctrl+Shift+V` | Shortcut to enter / exit voice mode (modifiers Ctrl/Shift/Alt/Meta + one letter key); **empty = disabled**, use the mic button instead |
148
160
  | `wakeWord` | empty (off) | Wake word (e.g. `你好小D`): speak it after entering to activate; empty = off. **May be said together with your command** — the wake word is stripped and never sent; fault-tolerant matching (edit distance ≤1 + a 3-char leading window absorbs homophones/fillers); **3-4 characters recommended** (single-char words get no tolerance; a 2-char word also absorbs any same-first-char 2-char word); must be repeated after each utterance split or barge-in; **toggle mode only**; not triggered while the agent is reading |
149
161
  | `spokenFormat` | `true` | Spoken-format system prompt: inject "short natural sentences, no Markdown decoration" into voice-mode replies only, **applies live** |
162
+ | `senseVoice` | `true` | Re-transcribe the finalized utterance with SenseVoice (punctuation + number normalization, more accurate; on by default). **Turning it off saves ~228 MB of models** and uses streaming recognition only (faster, less accurate) |
163
+ | `toolBeep` | `false` | Tool-call beep (off by default): when on, a short beep plays each time the agent calls a tool; off = silent |
150
164
  | `senseITN` | `true` | Batch 2 P0: SenseVoice inverse text normalization (number / date / currency; on by default) |
151
165
  | `captionFontSize` | `0` | Batch 3 P0: caption font tier 0=12px / 1=14px / 2=18px / 3=24px (default 0 is byte-equivalent to legacy) |
152
166
  | `captionMaxWidth` | `1` | Batch 3 P0: caption width tier 0=50vw / 1=70vw / 2=90vw |
153
167
  | `backchannelYield` | `true` | Batch 5 P1: yield semantics (ADR-0008); saying `嗯 / 对` while reading auto-pauses for 1.5 s; genuine speech still triggers hard barge-in. I10-exempt (default-on is a product decision); off = behavior identical to pre-change |
168
+ | `yieldMs` | `1500` | Yield-window length (ms, 500-3000): how long TTS frames are dropped after `backchannelYield` triggers; if you really want to speak in the window the normal `hardBreak` takes over, and playback resumes when the window ends |
154
169
 
155
170
  Effect timing: `voice`/`rate`/`ttsEngine`/`kokoroModel`/`spokenFormat` take effect **immediately** (TTS hot-swap); the rest apply on the next voice-mode entry. Defaults come from the plugin config (`base` layer) — they follow the config unless explicitly changed.
156
171
 
@@ -304,8 +319,8 @@ flowchart LR
304
319
  | Symptom | Fix |
305
320
  | --- | --- |
306
321
  | Mic click does nothing, red hint in the status bar | The browser denied mic permission: allow it in the address bar and retry |
307
- | Status bar stuck on `正在加载模型… x%` | Check the network; the model is large (160 MB) — `npm run prefetch` first; on mainland networks set `modelHost` to `https://hf-mirror.com` |
308
- | Status bar shows `语音模型下载失败` | Both mirrors are unreachable: check network/proxy and re-enter voice mode (resumable) |
322
+ | Status bar stuck on `Loading model… x%` | Check the network; the model is large (160 MB) — `npm run prefetch` first; on mainland networks set `modelHost` to `https://hf-mirror.com` |
323
+ | Status bar shows `Model download failed (<file>)` | Both mirrors are unreachable: check network/proxy and re-enter voice mode (resumable) |
309
324
  | Caption appears (overlay) but no sound | Check system volume/output; if autoplay is blocked, click anywhere on the page and retry |
310
325
  | Status bar shows `朗读连接失败:正在重试…` | Edge TTS unreachable (overseas service), auto-retries; if it persists, check network/proxy |
311
326
  | Poor recognition | Get closer to the mic, reduce ambient noise; if echo remains, raise the interrupt sensitivity by one step |
package/README.md CHANGED
@@ -3,10 +3,12 @@
3
3
  [![License: MIT](https://img.shields.io/github/license/qishuilalala/dsh-voice-mode?style=flat-square&color=blue)](LICENSE)
4
4
  [![Latest Release](https://img.shields.io/github/v/release/qishuilalala/dsh-voice-mode?style=flat-square&color=brightgreen&include_prereleases)](https://github.com/qishuilalala/dsh-voice-mode/releases)
5
5
  [![npm version](https://img.shields.io/npm/v/dsh-voice-mode?style=flat-square&color=orange)](https://www.npmjs.com/package/dsh-voice-mode)
6
- [![Tests: 380 passing](https://img.shields.io/badge/tests-380%20%E2%9C%93-2ea043?style=flat-square)](../../docs/rules/STATE.md)
6
+ [![Tests: 424 passing](https://img.shields.io/badge/tests-424%20%E2%9C%93-2ea043?style=flat-square)](../../docs/rules/STATE.md)
7
7
 
8
8
  DeepSeek Harness 语音双工对话模式:会话内一键进入 → 边说边出字的流式识别 → 停顿自动发送 → 最终答复按句流式朗读 + 实时字幕,开口即可打断(真 barge-in)。无需 API Key,识别模型在本地宿主端推理。
9
9
 
10
+ **中文** · [English](https://github.com/qishuilalala/dsh-voice-mode/blob/HEAD/plugin/dsh-voice-mode/README.en.md)
11
+
10
12
  > **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.
11
13
 
12
14
  ![dsh-voice-mode 全双工语音对话](https://raw.githubusercontent.com/qishuilalala/dsh-voice-mode/HEAD/assets/hero-banner.png)
@@ -50,8 +52,8 @@ DeepSeek Harness 语音双工对话模式:会话内一键进入 → 边说边
50
52
  - **输出链路**:只朗读最终答复的 `text-delta`(reasoning/工具调用不读),按句流式朗读(默认 Edge 云端;可切本地 VITS/Kokoro,中英混读选 Kokoro)+ 右下角实时字幕浮层;工具调用触发提示音;全文照常写入聊天记录;口语化提示词(设置 `spokenFormat`,默认开)让回复为自然短句、不带 Markdown 排版符号
51
53
  - **开口打断(barge-in)**:服务端 Silero VAD 帧级检测 + 回声门控(echoGateDb)三档灵敏度 → 本地静音 + host 合成队列作废 + 正在运行的回合取消(保留半截并自然续入新消息);朗读中自动切超灵敏档。开启唤醒词后打断**仍是开口即打断**(打断门控是 VAD,不是唤醒词;打断后回待机态)
52
54
  - **模型懒加载与进度**:首次使用自动下载识别/合成模型(`.part` 断点续传),状态条实时显示进度;可用 `npm run prefetch` 预下载
53
- - **设置**:设置 → Plugins → 插件配置 → 语音模式(voice-mode),可调朗读引擎/音色/语速/打断灵敏度/静音停顿/空闲超时/模型镜像/自动发送/交互模式/唤醒词/口语化提示词/字幕档位/让位语义;**音色可试听**(按当前音色+语速即时合成预览,自定义 ShortName 亦可)
54
- - **界面语言**:跟随浏览器语言(中文 / English;切换后刷新页面生效)
55
+ - **设置**:入口随 dsh 版本而不同(见下方「设置」),可调朗读引擎/音色/语速/打断灵敏度/静音停顿/空闲超时/模型镜像/自动发送/交互模式/唤醒词/口语化提示词/字幕档位/让位语义;**音色可试听**(按当前音色+语速即时合成预览,自定义 ShortName 亦可)
56
+ - **界面语言**:跟随 dsh 的语言设置(设置 → 通用 → 语言),**切换即时生效、无需刷新**——设置页、语音状态条、字幕、音色名称/性别/口音、错误提示全部随之变化;LLM 口语化提示词也按界面语言选中/英文版。插件词典注册在 dsh 官方 locale 服务的 `voice-mode` 命名空间,社区语言包可据此补充其它语言,缺失的语言回落英文。插件名称与描述在「插件」页同样按语言显示。
55
57
  - **容错**:麦克风被拒红点提示、模型下载失败可见提示、TTS 连接失败状态条提示(自动退避重试)、提交失败文字留在草稿、SSE 断线自动重连
56
58
  - **空闲退出**:5 分钟无活动自动退出并释放麦克风(**正在朗读计为活动**,长朗读不会中途下线;批 J 已微调默认 10→5)
57
59
 
@@ -88,7 +90,14 @@ bundle 插件安装后需重启 dsh 生效(Linux:`systemctl restart dsh`;
88
90
 
89
91
  ---
90
92
 
91
- ## ⚙️ 设置(设置 → Plugins → 插件配置 → 语音模式)
93
+ ## ⚙️ 设置
94
+
95
+ **所有 dsh 版本通用入口:设置(Settings)→ 语音模式(Voice Mode)**。另有按版本不同的次要入口(卡片内容一致):
96
+
97
+ - dsh ≤ 0.1.5:设置 → Plugins → 插件配置 → 语音模式
98
+ - dsh 0.1.6-alpha 及以后(含 0.1.7、0.2.0):左侧 **Plugins** → 已安装的 `dsh-voice-mode` → 详情页「语音模式」卡片
99
+ - dsh 0.1.7+ 起,设置保存在插件自有文件 `~/.dsh/voice-mode.settings.json`(`$DSH_HOME` 下),优先于 profile 配置里的同名键;首次运行会从旧 `settings.yaml(.imported)` 的 `voice-mode:` 段迁移一次;恢复默认请把该文件内容改成 `{}`(不要删除)。
100
+
92
101
 
93
102
  | 键 | 默认 | 说明 |
94
103
  | --- | --- | --- |
@@ -247,7 +256,7 @@ flowchart LR
247
256
  | 热词偏置 | 无 | 无(已移除,详见 v0.7.7 文档说明) |
248
257
  | 字幕 a11y | 无 | **4 档字号 + 3 档宽度 + 主题跟随** |
249
258
  | 唤醒词 | 无 | **轻量流式匹配 + 前缀语气词白名单** |
250
- | 兼容 dsh | — | **0.1.1-rc.2 起全版本(含 0.1.7-rc.1)** |
259
+ | 兼容 dsh | — | **0.1.1-rc.2 起全版本(含 0.2.0-rc.2)** |
251
260
 
252
261
  ---
253
262
 
@@ -325,7 +334,11 @@ src/tts-queue.ts host:逐会话 TTS 队列 + epoch 打断机制
325
334
  src/segmenter.ts host:句子切分 + 文本消毒(markdown 剥离 + 噪声字符剔除)
326
335
  src/asr.ts client:音频采集、VAD 分段、增量识别、唤醒词、按住说门控
327
336
  src/client.tsx client:麦克风按钮 + 模式切换按钮 + 状态条 + 字幕浮层 + 打断
328
- src/strings.ts client:中英文案字典(navigator.language)
337
+ src/strings.ts client:中英文案词典(zh / en 两份,键一一对应;有测试守卫)
338
+ src/i18n.ts client:接入官方 locale 服务(语言即时切换、语言包扩展、无服务时回退)
339
+ src/voice-catalog.ts host+client:音色目录单一数据源;src/voice-labels.ts 按语言生成音色/镜像标签
340
+ src/errors.ts host↔client:稳定错误码(host 不发自然语言,客户端按语言翻译)
341
+ src/prompts.ts host:LLM 口语化提示词(中/英)与试听例句(按音色语种)
329
342
  ```
330
343
 
331
344
  ---