@memef1f1y/dsh-plugin-tts 0.6.4 → 0.6.7

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.
Files changed (37) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +51 -51
  2. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +28 -28
  4. package/.github/pull_request_template.md +7 -7
  5. package/.github/workflows/contrib-triage.yml +66 -66
  6. package/.github/workflows/linked-issue.yml +21 -21
  7. package/.github/workflows/publish.yml +63 -0
  8. package/.github/workflows/stale.yml +30 -30
  9. package/.github/workflows/test.yml +33 -33
  10. package/.github/workflows/welcome.yml +22 -22
  11. package/ANALYSIS.md +205 -205
  12. package/PR-REVIEW.md +74 -74
  13. package/README.md +335 -335
  14. package/TODO.md +34 -23
  15. package/docs/HOST-CONTRACT.md +36 -36
  16. package/docs/RVC-GUIDE.md +390 -390
  17. package/docs/USER-GUIDE.md +389 -389
  18. package/docs/acceptance-checklist.md +147 -147
  19. package/docs/adaptive-chunked-playback.md +194 -194
  20. package/docs/macos-test-prompt.md +230 -230
  21. package/docs/windows-gpu-verify-prompt.md +151 -151
  22. package/lib/client.js +7164 -7164
  23. package/lib/index.mjs +3374 -3371
  24. package/package.json +51 -52
  25. package/rvc-server.py +564 -564
  26. package/tests/README.md +45 -45
  27. package/tests/client-load.mjs +406 -406
  28. package/tests/e2e-compact-index.mjs +86 -86
  29. package/tests/e2e-index-ab.mjs +138 -138
  30. package/tests/e2e-real-rvc.mjs +122 -122
  31. package/tests/i18n-keys.mjs +82 -82
  32. package/tests/package-runtime-patch.mjs +88 -88
  33. package/tests/rvc-server-live.mjs +230 -230
  34. package/tests/smoke.mjs +1284 -1284
  35. package/tools/gen-ui-preview.mjs +174 -174
  36. package/tools/mac-verify.sh +158 -158
  37. package/tools/package-runtime.py +214 -214
package/README.md CHANGED
@@ -1,337 +1,337 @@
1
- <p align="center">
2
- <img src="logo.png" alt="dsh-plugin-tts" width="140" />
3
- </p>
4
-
5
- <h1 align="center">dsh-plugin-tts</h1>
6
-
7
- <p align="center">
8
- <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="license"></a>
9
- <a href="https://github.com/awesome-dsh-plugin/awesome-dsh-plugin"><img src="https://awesome-dsh-plugin.com/badge.svg" alt="Awesome"></a>
10
- <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-22%2B-blue" alt="node"></a>
11
- <a href="tests/smoke.mjs"><img src="https://img.shields.io/badge/tests-133%20passed-success" alt="tests"></a>
12
- <a href="https://github.com/1624318455/dsh-plugin-tts"><img src="https://img.shields.io/github/stars/1624318455/dsh-plugin-tts" alt="stars"></a>
13
- <a href="https://github.com/1624318455/dsh-plugin-tts/commits/main"><img src="https://img.shields.io/github/last-commit/1624318455/dsh-plugin-tts" alt="last commit"></a>
14
- </p>
15
-
16
- ## Links
17
-
18
- - **[中文 README](README.zh.md)**(简体中文,与本页逐节对应)
19
- - **[User Guide (执行手册)](docs/USER-GUIDE.md)** — step-by-step, for first-time users
20
- - **[RVC Custom Voice Guide](docs/RVC-GUIDE.md)** — custom voices · chunked progressive playback · compact index · voice packs · portable runtime
21
- - **[Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md)** — local reference-audio voices
22
- - **[CosyVoice Guide](docs/COSYVOICE-GUIDE.md)** — local zero-shot prompt cloning (CosyVoice-2.0-0.5B)
23
- - **[Cloud TTS Guide](docs/CLOUD-GUIDE.md)** — paid Google voices · API key · usage & billing caliber
24
- - **[Edge TTS Guide](docs/EDGE-GUIDE.md)** — default online reading
25
- - **[Adaptive chunked playback design](docs/adaptive-chunked-playback.md)** — how gapless long reads work
26
-
27
- ---
28
-
29
- # dsh-plugin-tts — Edge TTS + RVC / Index-TTS2 / CosyVoice / Cloud voices for DeepSeek Harness
30
-
31
- A dual-sided (Host + Web UI) DeepSeek Harness plugin that reads assistant replies
32
- aloud — Microsoft Edge's free online TTS out of the box, **your own RVC voice
33
- models** for custom voices, **local Index-TTS2 reference-audio voices**,
34
- **local CosyVoice zero-shot prompt clones** (CosyVoice-2.0-0.5B), or
35
- **paid Google Cloud TTS voices** (Chinese Standard/Wavenet). Long replies stream
36
- with **gapless adaptive chunked playback**; voices install **one-click from a
37
- voice-pack registry**; a **portable RVC runtime** means no RVC WebUI install is needed.
38
-
39
- > 📖 **First time? See the [user guide (执行手册)](docs/USER-GUIDE.md)** — every step
40
- > covers "what / how / how to tell it worked": read-aloud, RVC voices and
41
- > voice-pack downloads.
42
-
43
- ## Features
44
-
45
- 1. **Read-aloud button** on every finalized assistant message (in the
46
- copy / feedback / branch action row): click to speak that message (the
47
- button shows an animated equalizer), click again to stop.
48
- 2. **Auto-read toggle** in the composer tool row (between the command and the
49
- access-mode buttons): when on, every newly completed assistant reply is
50
- read aloud automatically (the toggle gets a circular highlight); when off,
51
- nothing is auto-read.
52
- 3. **Voice settings panel** under 设置 → 插件 → 语音:
53
- - **TTS provider**: Edge TTS (free, no API key) / custom RVC voice /
54
- local Index-TTS2 voice / local CosyVoice clone / Google Cloud TTS (paid, API key)
55
- - **Voice**: 22 live-verified Edge TTS voices (default 晓萱 zh-CN-XiaoxuanNeural);
56
- 8 Cloud voices in the cmn-CN group (default cmn-CN-Wavenet-A, free-form id allowed)
57
- - **Sound tuning**: rate / pitch / volume (0 = default, shared by Edge & Cloud)
58
- - **RVC config**: service URL + model (.pth) / index (.index) picker, base voice,
59
- voice tuning and advanced params — see the [RVC Guide](docs/RVC-GUIDE.md)
60
- - **Index-TTS2 config**: service URL (default 7880) + reference-voice
61
- picker/refresh/upload + clean-text toggle + emotion control + sampling
62
- params — see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md)
63
- - **CosyVoice config**: service URL (default 7890) + prompt-audio picker/refresh/upload +
64
- prompt transcript (required, in order and in full) + speed (0.5–2.0) + seed (0 = random) —
65
- see the [CosyVoice Guide](docs/COSYVOICE-GUIDE.md)
66
- - **Cloud config**: API Key (Host-file-only, write-only input) + Project ID (optional) +
67
- test button + this month's local usage per tier (Standard 4M / Wavenet-Neural2-Chirp3 1M) —
1
+ <p align="center">
2
+ <img src="logo.png" alt="dsh-plugin-tts" width="140" />
3
+ </p>
4
+
5
+ <h1 align="center">dsh-plugin-tts</h1>
6
+
7
+ <p align="center">
8
+ <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="license"></a>
9
+ <a href="https://github.com/awesome-dsh-plugin/awesome-dsh-plugin"><img src="https://awesome-dsh-plugin.com/badge.svg" alt="Awesome"></a>
10
+ <a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-22%2B-blue" alt="node"></a>
11
+ <a href="tests/smoke.mjs"><img src="https://img.shields.io/badge/tests-133%20passed-success" alt="tests"></a>
12
+ <a href="https://github.com/1624318455/dsh-plugin-tts"><img src="https://img.shields.io/github/stars/1624318455/dsh-plugin-tts" alt="stars"></a>
13
+ <a href="https://github.com/1624318455/dsh-plugin-tts/commits/main"><img src="https://img.shields.io/github/last-commit/1624318455/dsh-plugin-tts" alt="last commit"></a>
14
+ </p>
15
+
16
+ ## Links
17
+
18
+ - **[中文 README](README.zh.md)**(简体中文,与本页逐节对应)
19
+ - **[User Guide (执行手册)](docs/USER-GUIDE.md)** — step-by-step, for first-time users
20
+ - **[RVC Custom Voice Guide](docs/RVC-GUIDE.md)** — custom voices · chunked progressive playback · compact index · voice packs · portable runtime
21
+ - **[Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md)** — local reference-audio voices
22
+ - **[CosyVoice Guide](docs/COSYVOICE-GUIDE.md)** — local zero-shot prompt cloning (CosyVoice-2.0-0.5B)
23
+ - **[Cloud TTS Guide](docs/CLOUD-GUIDE.md)** — paid Google voices · API key · usage & billing caliber
24
+ - **[Edge TTS Guide](docs/EDGE-GUIDE.md)** — default online reading
25
+ - **[Adaptive chunked playback design](docs/adaptive-chunked-playback.md)** — how gapless long reads work
26
+
27
+ ---
28
+
29
+ # dsh-plugin-tts — Edge TTS + RVC / Index-TTS2 / CosyVoice / Cloud voices for DeepSeek Harness
30
+
31
+ A dual-sided (Host + Web UI) DeepSeek Harness plugin that reads assistant replies
32
+ aloud — Microsoft Edge's free online TTS out of the box, **your own RVC voice
33
+ models** for custom voices, **local Index-TTS2 reference-audio voices**,
34
+ **local CosyVoice zero-shot prompt clones** (CosyVoice-2.0-0.5B), or
35
+ **paid Google Cloud TTS voices** (Chinese Standard/Wavenet). Long replies stream
36
+ with **gapless adaptive chunked playback**; voices install **one-click from a
37
+ voice-pack registry**; a **portable RVC runtime** means no RVC WebUI install is needed.
38
+
39
+ > 📖 **First time? See the [user guide (执行手册)](docs/USER-GUIDE.md)** — every step
40
+ > covers "what / how / how to tell it worked": read-aloud, RVC voices and
41
+ > voice-pack downloads.
42
+
43
+ ## Features
44
+
45
+ 1. **Read-aloud button** on every finalized assistant message (in the
46
+ copy / feedback / branch action row): click to speak that message (the
47
+ button shows an animated equalizer), click again to stop.
48
+ 2. **Auto-read toggle** in the composer tool row (between the command and the
49
+ access-mode buttons): when on, every newly completed assistant reply is
50
+ read aloud automatically (the toggle gets a circular highlight); when off,
51
+ nothing is auto-read.
52
+ 3. **Voice settings panel** under 设置 → 插件 → 语音:
53
+ - **TTS provider**: Edge TTS (free, no API key) / custom RVC voice /
54
+ local Index-TTS2 voice / local CosyVoice clone / Google Cloud TTS (paid, API key)
55
+ - **Voice**: 22 live-verified Edge TTS voices (default 晓萱 zh-CN-XiaoxuanNeural);
56
+ 8 Cloud voices in the cmn-CN group (default cmn-CN-Wavenet-A, free-form id allowed)
57
+ - **Sound tuning**: rate / pitch / volume (0 = default, shared by Edge & Cloud)
58
+ - **RVC config**: service URL + model (.pth) / index (.index) picker, base voice,
59
+ voice tuning and advanced params — see the [RVC Guide](docs/RVC-GUIDE.md)
60
+ - **Index-TTS2 config**: service URL (default 7880) + reference-voice
61
+ picker/refresh/upload + clean-text toggle + emotion control + sampling
62
+ params — see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md)
63
+ - **CosyVoice config**: service URL (default 7890) + prompt-audio picker/refresh/upload +
64
+ prompt transcript (required, in order and in full) + speed (0.5–2.0) + seed (0 = random) —
65
+ see the [CosyVoice Guide](docs/COSYVOICE-GUIDE.md)
66
+ - **Cloud config**: API Key (Host-file-only, write-only input) + Project ID (optional) +
67
+ test button + this month's local usage per tier (Standard 4M / Wavenet-Neural2-Chirp3 1M) —
68
68
  see the [Cloud Guide](docs/CLOUD-GUIDE.md)
69
- - **Voice packs**: one-click install of voices from a registry
70
- - **Preview**: type text and press the play (triangle) button — a spinning
71
- loader shows while it is synthesizing/playing (click again to stop),
72
- failures show an inline message.
73
- 4. **RVC custom voices**: read with your own trained RVC models, computed
74
- locally (index-free mode, advanced params — see the
75
- [RVC guide](docs/RVC-GUIDE.md)).
76
- 5. **Gapless long reads**: adaptive chunked progressive playback — probe-calibrated
77
- chunk size, play-while-converting, Web Audio sample-accurate joins, no gaps
78
- between chunks (see the [design doc](docs/adaptive-chunked-playback.md)).
79
- 6. **Mini player** while reading: pause / resume + playback speed (1x / 1.25x /
80
- 1.5x) on the message's action row; chunked long reads surface a visible
81
- "chunk x/y" counter.
82
- 7. **Themed tooltips & RVC onboarding**: hover tooltips use the app's theme
83
- tokens (`--dsw-*`); the RVC panel opens with a first-time 3-step guide
84
- (per-OS startup commands + one-click diagnostics).
85
- 8. **Download audio**: a download button on each message saves the synthesized
86
- audio — MP3 for Edge/Cloud reads, WAV for local (RVC/Index-TTS2/CosyVoice)
87
- reads — reusing the in-session cache so a just-read message downloads
88
- instantly. Long chunked reads have no single output file yet and report
69
+ - **Voice packs**: one-click install of voices from a registry
70
+ - **Preview**: type text and press the play (triangle) button — a spinning
71
+ loader shows while it is synthesizing/playing (click again to stop),
72
+ failures show an inline message.
73
+ 4. **RVC custom voices**: read with your own trained RVC models, computed
74
+ locally (index-free mode, advanced params — see the
75
+ [RVC guide](docs/RVC-GUIDE.md)).
76
+ 5. **Gapless long reads**: adaptive chunked progressive playback — probe-calibrated
77
+ chunk size, play-while-converting, Web Audio sample-accurate joins, no gaps
78
+ between chunks (see the [design doc](docs/adaptive-chunked-playback.md)).
79
+ 6. **Mini player** while reading: pause / resume + playback speed (1x / 1.25x /
80
+ 1.5x) on the message's action row; chunked long reads surface a visible
81
+ "chunk x/y" counter.
82
+ 7. **Themed tooltips & RVC onboarding**: hover tooltips use the app's theme
83
+ tokens (`--dsw-*`); the RVC panel opens with a first-time 3-step guide
84
+ (per-OS startup commands + one-click diagnostics).
85
+ 8. **Download audio**: a download button on each message saves the synthesized
86
+ audio — MP3 for Edge/Cloud reads, WAV for local (RVC/Index-TTS2/CosyVoice)
87
+ reads — reusing the in-session cache so a just-read message downloads
88
+ instantly. Long chunked reads have no single output file yet and report
89
89
  "not supported" instead of starting a wasteful re-synthesis.
90
- 9. **Read selected text**: selecting text in a message shows a floating
91
- "朗读选中" chip — click it to read just that selection.
92
- 10. **Streaming long reads (Edge too)**: long plain-Edge reads also stream
93
- progressively (first chunk plays while the rest synthesize), reusing the
94
- gapless chunked pipeline — no more waiting for full synthesis.
95
- 11. **Approval voice alerts**: optional voice broadcast of Agent approval events.
96
- When enabled, an approval request (`approval/asked`) is announced aloud and
97
- **interrupts the current read** (the agent is waiting on the decision); an
98
- approval result (`approval/decided`) is announced only when idle. Alerts
99
- always use Edge TTS with their own alert voice (independent of the RVC
100
- service), are deduplicated by approval id, and off by default. (Scope note:
101
- task-completion announcements are deferred to a later phase — the jobs
102
- subsystem has no session-event channel this plugin can observe yet.)
103
- 12. **Clean reads, quiet RVC**: message Markdown (code blocks, tables, links,
104
- quotes, task lists) is cleaned before reading — no symbol soup; an opt-in
105
- "read raw Markdown symbols" toggle keeps verbatim reads for source code.
106
- With the Edge provider the RVC panel stays fully hidden behind a single
107
- "need a cloned voice?" entry, so casual reading is zero-config.
108
-
109
- ## Requirements
110
-
111
- - DeepSeek Harness `web` profile (`dsh web`)
112
- - Node.js >= 22 (the worker uses the native `WebSocket`)
113
- - For **local-voice providers only** (nothing to install for Edge/Cloud):
114
- - **RVC custom voices**: a local RVC inference environment (an RVC WebUI
115
- or the portable runtime) and a running `rvc-server.py` — see the
116
- [RVC Guide](docs/RVC-GUIDE.md) → "启动本地 RVC 服务" and the
117
- [User Guide](docs/USER-GUIDE.md) §4.2. macOS users start there too.
118
- - **Index-TTS2 voices**: the local `index-tts2-nvidia` bundle's API service
119
- (`启动api服务.bat`, default port 7880) — see the
120
- [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md).
121
- - **CosyVoice clones**: the local CosyVoice-2.0-0.5B bundle's `cosy-server.py`
122
- (`启动cosy服务.bat`, default port 7890) — see the
123
- [CosyVoice Guide](docs/COSYVOICE-GUIDE.md).
124
-
125
- ## Install
126
-
127
- Four equivalent ways (pick any one):
128
-
129
- ```sh
130
- # dsh-market UI: search the market for the plugin name and install
131
- # npm package:
132
- dsh plugin --profile web add "@memef1f1y/dsh-plugin-tts"
133
- # GitHub source:
134
- dsh plugin --profile web add "github:1624318455/dsh-plugin-tts#main"
135
- # or local development:
136
- dsh plugin --profile web add "file:/path/to/dsh-plugin-tts/plugin"
137
- ```
138
-
139
- Restart `dsh web`; the plugin then loads automatically as a profile bundle.
140
- Uninstalling any one of the above first is required before installing another:
141
- they all register the same loader entry id (`tts`), and the installer refuses
142
- duplicates (it rolls back instead of overwriting).
143
-
144
- ## Voices (live-verified, Edge TTS)
145
-
146
- | Region | Voices |
147
- |---|---|
148
- | Simplified Chinese | Xiaoxuan 晓萱 · Xiaoyi 晓伊 · Yunxi 云希 · Yunyang 云扬 · Xiaoxiao 晓晓 · Yunjian 云健 · Yunxia 云夏 · liaoning-Xiaobei 晓北 · shaanxi-Xiaoni 晓妮 |
149
- | Taiwan | HsiaoChen 曉臻 · HsiaoYu 曉雨 · YunJhe 雲哲 |
150
- | Hong Kong | HiuGaai 曉佳 · HiuMaan 曉曼 · WanLung 雲龍 |
151
- | English | Aria · Jenny · Guy · Sonia (UK) |
152
- | Other | Nanami 七海 (ja-JP) · SunHi (ko-KR) · Denise (fr-FR) |
153
-
154
- > Note: legacy voices such as Xiaohan / Xiaomeng / Xiaorui / Xiaoshuang were
155
- > removed by the Edge endpoint (`1007 Unsupported voice`) and are not listed.
156
-
157
- ## Architecture
158
-
159
- | Layer | Location | Role |
160
- |---|---|---|
161
- | Host | `lib/index.mjs` | Registers webServer routes: `/dsh-tts-api/speak` (synthesis / chunk queue, all providers), `/dsh-tts-audio/<id>` (audio bytes), `/dsh-tts-api/rvc-next` (next chunk / job cancel), `/dsh-tts-api/rvc-files` + `/rvc-compact-index` + `/rvc-packs*` (RVC service proxy / packs), `/dsh-tts-api/index-*` and `/dsh-tts-api/cosy-*` (local service proxy + config), `/dsh-tts-api/cloud-*` (Cloud key/usage/test), `/dsh-tts-api/notify` (approval-alert queue), `/dsh-tts-api/diagnose` (one-click diagnostics); runs a zero-dependency Edge worker via `node -e` |
162
- | Client | `lib/client.js` | Web Audio chunk player (sample-accurate joins, `<audio>` fallback) in `shell.overlay` + the UI entries (read-aloud button / auto-read toggle / settings panel); talks to the Host through `fetch` |
163
-
164
- The TTS worker mirrors [node-edge-tts@1.2.10](https://github.com/SchneeHertz/node-edge-tts):
165
- `Sec-MS-GEC` query params (ticks rounded to the 5-minute boundary),
166
- `Sec-MS-GEC-Version=1-143.0.3650.75`, `Path:audio` binary framing, `xml:lang`
167
- derived from the voice locale, one retry on abnormal (1006) closures. Audio is
168
- `audio-24khz-48kbitrate-mono-mp3`.
169
-
170
- ## Edge cases handled
171
-
172
- - Clicking the read button of the message being auto-read stops it; another
173
- message's button switches to manual reading.
174
- - Disabling auto-read never interrupts a manual read; it stops auto reads.
175
- - A newly completed message (auto on) interrupts the current read; text-less
176
- messages are skipped; session switches only stop auto reads.
177
- - Stopping / switching messages **eagerly cancels** the active RVC chunked job on
178
- the Host, so the local conversion service stops scheduling new chunks and
179
- releases GPU/memory promptly (no waiting for the lazy GC).
180
- - Repeatedly reading the same text + voice **reuses the in-session audio cache**
181
- (no re-synthesis); if the cached backing file was cleaned by the OS, it
182
- transparently re-synthesizes instead of serving a stale 404 URL.
183
- - If an Edge voice was removed by the endpoint (`1007 Unsupported voice`), the
184
- voice is pruned from the picker and the plugin auto-falls back to the default.
185
- - Audio is **autoplay-unlocked** on the first user gesture (Web Audio context
186
- resumed + silent clip) so reads aren't silently blocked by browser policy.
187
- - `Esc` / `S` (outside an input) stops the current read-aloud.
188
- - Synthesis / playback failures **surface a themed toast** (message read-aloud and
189
- auto-read no longer fail silently; the preview panel keeps its inline error).
190
- In RVC mode the error toast carries a one-click **"read with Edge TTS instead"**
191
- action; with the opt-in toggle **"auto-switch to Edge TTS when RVC fails"** in
192
- the RVC settings (off by default — RVC is fully local, auto-fallback sends the
193
- text to Microsoft's endpoint), a failed RVC read silently retries with the RVC
194
- base voice via Edge TTS and shows a warn toast.
195
- - **Smart chunking** never splits URLs / emails / decimals / versions ("3.14")
196
- mid-token — hard cuts slide to word/punctuation boundaries, and a tiny trailing
197
- sentence merges into the previous chunk instead of reading like a stutter.
198
- - **Approval voice alerts** (opt-in): the Host subscribes to the session/event
199
- firehose (`approval/asked` / `approval/decided`), dedupes by approval id, and
200
- the client polls `/dsh-tts-api/notify?s=N` — the first poll baseline-syncs the
201
- cursor so a page refresh never replays stale alerts; announcements are silent
202
- on failure (no error toasts while the agent loops).
203
-
204
- ## Settings persistence
205
-
206
- Layered storage:
207
-
208
- - **Host file** (`~/.dsh/tts-rvc/settings.json`,
209
- `{ version: 1, rvc: …, index: …, cosy: …, cloud: … }`):
210
- service-class config — RVC service URL/model/index paths, Index-TTS2 and
211
- CosyVoice service URLs, Cloud API key (+ optional project ID). Shared across
212
- browsers, survives browser-data clears and incognito. Served/updated through
213
- `GET /dsh-tts-api/rvc-config` + `POST /dsh-tts-api/rvc-config-save`
214
- (and the matching `index-config`, `cosy-config`, `cloud-config` routes;
215
- legacy `localStorage` values migrate up once, then the file wins).
216
- - **localStorage** (`dsh-tts-settings`): UI prefs only — voice, auto-read
217
- toggle, provider, sound tuning, the raw-Markdown toggle, approval-alert and
218
- remaining RVC prefs. Never stores the service URL / model / index.
219
-
220
- A "Reset to defaults" button in the settings panel restores defaults and clears
221
- both layers (best-effort on the Host file).
222
-
223
- ## Custom voice (RVC)
224
-
225
- Use your locally trained **RVC model** for voice conversion: switch the TTS
226
- provider to "自定义音色(RVC)" in the settings panel. **First-time RVC users
227
- need two things**: a model file (`.pth`) and a running local RVC service — see
228
- the [RVC Guide](docs/RVC-GUIDE.md) or [User Guide](docs/USER-GUIDE.md) §4.2 for
229
- macOS/Windows/Linux startup commands. The full story — service startup, panel
230
- config, gapless chunked playback, compact index, voice-pack registry install,
231
- portable runtime, settings reference and troubleshooting — lives in the
232
- **[RVC Custom Voice Guide](docs/RVC-GUIDE.md)**.
233
-
234
- > Public pack registry example: [rvc-for-tts](https://github.com/1624318455/rvc-for-tts)
235
- > (设置 → 语音 → 音色包 → registry URL: `https://raw.githubusercontent.com/1624318455/rvc-for-tts/main`).
236
-
237
- ## Troubleshooting (Edge TTS)
238
-
239
- - **403 / `Sec-MS-GEC` rejected**: the Edge endpoint protocol or version check
240
- changed; update `CHROMIUM_FULL_VERSION` / `TRUSTED_CLIENT_TOKEN` inside the
241
- worker in `lib/index.mjs`.
242
- - **`1007 Unsupported voice`**: the selected voice was removed from the
243
- endpoint; pick one from the table above.
244
- - **No sound**: check system volume, the browser autoplay policy (interact
245
- with the page once), or the synthesis logs (`[tts]` errors in the `dsh web`
246
- console).
247
-
248
- > RVC-specific troubleshooting: [RVC Guide → Troubleshooting](docs/RVC-GUIDE.md#troubleshooting).
249
-
250
- ## FAQ
251
-
252
- **Q: Is it big?**
253
- - Default experience (Edge TTS): the plugin itself is tiny (MB scale) — **no service or model to download**.
254
- - You only need a local RVC portable package if you want custom voices (RVC). Its size mostly comes from the **bundled offline Python runtime + inference deps + pretrained models**:
255
- | Platform | Archive | Extracted |
256
- |---|---:|---:|
257
- | macOS (Apple Silicon) | ~660 MB | ~1.3 GB |
258
- | Windows (CPU-minimal) | ~1–2 GB | ~2–3 GB |
259
- | Windows (with NVIDIA GPU) | ~6 GB | ~7 GB |
260
- - These are self-contained runtimes; the **full RVC WebUI is 7.8 GB** — we don't ship the WebUI / training / realtime parts this plugin doesn't need.
261
- - Index-TTS2 / CosyVoice also ship as local bundles (sizes vary by release — see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md) / [CosyVoice Guide](docs/COSYVOICE-GUIDE.md) preparation sections).
262
-
263
- **Q: Are the dependencies big?**
264
- - The runtime is heavy but **you don't install anything**: the portable package bundles Python, ffmpeg (Windows) / PyAV (macOS), and all inference deps. Unzip and run — no compile, no env setup.
265
- - The plugin itself has minimal deps and only loads what it actually uses.
266
-
267
- **Q: Do I need a local TTS model?**
268
- - With the default Edge TTS or Cloud TTS: **no** — they synthesize online.
269
- - With custom voices (RVC): you need **your own** RVC voice model (`.pth`), optionally a `.index`; the pretrained hubert / rmvpe are already bundled — you only provide your trained model.
270
- - With Index-TTS2 / CosyVoice: no training needed — you provide **reference/prompt audio** (a few seconds of clear speech) to the local bundle and pick it in the panel; see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md) and [CosyVoice Guide](docs/COSYVOICE-GUIDE.md).
271
-
272
- **Q: Is it easy to install?**
273
- - Install the plugin normally, then for RVC: download the portable package for your platform → unzip → run the launcher (double-click `.command` on macOS, `.bat` on Windows) → drop your `.pth` into `assets/weights` → pick it in the plugin panel.
274
- - Index-TTS2 / CosyVoice follow the same three steps (bundle → keep its service running → pick a voice in the panel); Cloud TTS only needs an API key pasted into settings. Each provider guide walks through it.
275
- - No compile, no manual Python/ffmpeg install. Note: **the first macOS launch is slow (tens of seconds)** while macOS scans the extracted runtimes (one-time); later launches take a few seconds.
276
-
277
- **Q: Do I need a paid API?**
278
- - No for Edge TTS (free, no API key) and RVC / Index-TTS2 / CosyVoice (fully
279
- local and free — but each needs its local service package running, see
280
- Requirements above).
281
- - Google Cloud TTS is pay-as-you-go and needs your own API key: Chinese
282
- Standard voices are free for the first 4M chars/month, Wavenet/Neural2/Chirp
283
- for the first 1M chars/month (local counters; Google Cloud Billing is
284
- authoritative). See the [Cloud Guide](docs/CLOUD-GUIDE.md).
285
- - Note: Edge TTS is Microsoft's public client-side, free capability — fine for personal use; check Microsoft's terms for commercial / heavy usage.
286
-
287
- **Q: Did this modify the DSH core?**
288
- - No. It's an **independent plugin** loaded through dsh's plugin mechanism. It doesn't touch the DSH main program and can be installed / paused / uninstalled anytime without affecting DSH or other plugins.
289
-
290
- **Other common questions**
291
- - **Do I need a GPU?** No — CPU works. For speed you can use Apple Silicon MPS (macOS) or an NVIDIA GPU (Windows, which needs the bigger CUDA torch build).
292
- - **Privacy?** RVC conversion is fully local — audio never leaves your machine. Edge TTS sends the text-to-read to Microsoft's endpoint for online synthesis (assess which voice before choosing).
293
- - **Apple Silicon only?** The macOS build is arm64 (M1–M5); Intel Macs would need a separate x86_64 build.
294
-
295
- ## UI language (i18n)
296
-
297
- The settings panel has an **Interface language** selector at the top:
298
- **Auto (follow browser) / 中文 / English**.
299
- - Default "Auto" follows the browser/system language (Simplified Chinese and
300
- others → Chinese, everything else → English).
301
- - Switching applies immediately and is **persisted** to localStorage
302
- (`dsh-tts-lang`), surviving page reloads.
303
- - Covers the whole settings panel, bubble/read-aloud buttons, diagnostics,
304
- voice-pack panel, plus RVC service errors/progress hints.
305
-
306
- ## Development
307
-
308
- ```sh
309
- node tests/smoke.mjs # fake-ctx route registration + real Edge TTS synthesis + audio serve assertions
310
- npm run test:all # full: smoke + live + patch + i18n + client-load
311
- ```
312
-
313
- Hot-reload after editing `lib/` (on Windows a `file:` install is a COPY, not a
314
- symlink, so the running dsh reads the profile copy):
315
-
316
- ```powershell
317
- Copy-Item lib/* $env:USERPROFILE\.dsh\profiles\web\node_modules\@memef1f1y\dsh-plugin-tts\lib\ -Recurse -Force
318
- # then refresh the browser (bundles are re-read from disk per request; never use pnpm install --force)
319
- ```
320
-
321
- ## Known limits
322
-
323
- - Voice / auto-read toggle / provider / RVC settings are persisted in layers
324
- (Host file for service config, localStorage for UI prefs — see "Settings
325
- persistence" above) and survive refresh (see "Settings persistence" above); the
326
- audio cache itself is in-session only (files live in the OS temp dir, cleaned
327
- by the OS), so a full restart re-synthesizes the first read of each text.
328
- - Synthesized audio is written to the OS temp dir and cleaned by the OS.
329
- - zh/en **layout/visual** fitting (English text is longer; may wrap/overflow; theme
330
- vars `--dsw-*`) must be eyeballed in the real dsh UI with the plugin loaded — this
331
- plugin ships no standalone HTML (its UI is slot-injected by the dsh web host), so
332
- it cannot be headless-screenshotted here (`tests/client-load.mjs` asserts the
333
- in-memory render only, not real DOM/CSS).
334
-
335
- ## License
336
-
337
- MIT
90
+ 9. **Read selected text**: selecting text in a message shows a floating
91
+ "朗读选中" chip — click it to read just that selection.
92
+ 10. **Streaming long reads (Edge too)**: long plain-Edge reads also stream
93
+ progressively (first chunk plays while the rest synthesize), reusing the
94
+ gapless chunked pipeline — no more waiting for full synthesis.
95
+ 11. **Approval voice alerts**: optional voice broadcast of Agent approval events.
96
+ When enabled, an approval request (`approval/asked`) is announced aloud and
97
+ **interrupts the current read** (the agent is waiting on the decision); an
98
+ approval result (`approval/decided`) is announced only when idle. Alerts
99
+ always use Edge TTS with their own alert voice (independent of the RVC
100
+ service), are deduplicated by approval id, and off by default. (Scope note:
101
+ task-completion announcements are deferred to a later phase — the jobs
102
+ subsystem has no session-event channel this plugin can observe yet.)
103
+ 12. **Clean reads, quiet RVC**: message Markdown (code blocks, tables, links,
104
+ quotes, task lists) is cleaned before reading — no symbol soup; an opt-in
105
+ "read raw Markdown symbols" toggle keeps verbatim reads for source code.
106
+ With the Edge provider the RVC panel stays fully hidden behind a single
107
+ "need a cloned voice?" entry, so casual reading is zero-config.
108
+
109
+ ## Requirements
110
+
111
+ - DeepSeek Harness `web` profile (`dsh web`)
112
+ - Node.js >= 22 (the worker uses the native `WebSocket`)
113
+ - For **local-voice providers only** (nothing to install for Edge/Cloud):
114
+ - **RVC custom voices**: a local RVC inference environment (an RVC WebUI
115
+ or the portable runtime) and a running `rvc-server.py` — see the
116
+ [RVC Guide](docs/RVC-GUIDE.md) → "启动本地 RVC 服务" and the
117
+ [User Guide](docs/USER-GUIDE.md) §4.2. macOS users start there too.
118
+ - **Index-TTS2 voices**: the local `index-tts2-nvidia` bundle's API service
119
+ (`启动api服务.bat`, default port 7880) — see the
120
+ [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md).
121
+ - **CosyVoice clones**: the local CosyVoice-2.0-0.5B bundle's `cosy-server.py`
122
+ (`启动cosy服务.bat`, default port 7890) — see the
123
+ [CosyVoice Guide](docs/COSYVOICE-GUIDE.md).
124
+
125
+ ## Install
126
+
127
+ Four equivalent ways (pick any one):
128
+
129
+ ```sh
130
+ # dsh-market UI: search the market for the plugin name and install
131
+ # npm package:
132
+ dsh plugin --profile web add "@memef1f1y/dsh-plugin-tts"
133
+ # GitHub source:
134
+ dsh plugin --profile web add "github:1624318455/dsh-plugin-tts#main"
135
+ # or local development:
136
+ dsh plugin --profile web add "file:/path/to/dsh-plugin-tts/plugin"
137
+ ```
138
+
139
+ Restart `dsh web`; the plugin then loads automatically as a profile bundle.
140
+ Uninstalling any one of the above first is required before installing another:
141
+ they all register the same loader entry id (`tts`), and the installer refuses
142
+ duplicates (it rolls back instead of overwriting).
143
+
144
+ ## Voices (live-verified, Edge TTS)
145
+
146
+ | Region | Voices |
147
+ |---|---|
148
+ | Simplified Chinese | Xiaoxuan 晓萱 · Xiaoyi 晓伊 · Yunxi 云希 · Yunyang 云扬 · Xiaoxiao 晓晓 · Yunjian 云健 · Yunxia 云夏 · liaoning-Xiaobei 晓北 · shaanxi-Xiaoni 晓妮 |
149
+ | Taiwan | HsiaoChen 曉臻 · HsiaoYu 曉雨 · YunJhe 雲哲 |
150
+ | Hong Kong | HiuGaai 曉佳 · HiuMaan 曉曼 · WanLung 雲龍 |
151
+ | English | Aria · Jenny · Guy · Sonia (UK) |
152
+ | Other | Nanami 七海 (ja-JP) · SunHi (ko-KR) · Denise (fr-FR) |
153
+
154
+ > Note: legacy voices such as Xiaohan / Xiaomeng / Xiaorui / Xiaoshuang were
155
+ > removed by the Edge endpoint (`1007 Unsupported voice`) and are not listed.
156
+
157
+ ## Architecture
158
+
159
+ | Layer | Location | Role |
160
+ |---|---|---|
161
+ | Host | `lib/index.mjs` | Registers webServer routes: `/dsh-tts-api/speak` (synthesis / chunk queue, all providers), `/dsh-tts-audio/<id>` (audio bytes), `/dsh-tts-api/rvc-next` (next chunk / job cancel), `/dsh-tts-api/rvc-files` + `/rvc-compact-index` + `/rvc-packs*` (RVC service proxy / packs), `/dsh-tts-api/index-*` and `/dsh-tts-api/cosy-*` (local service proxy + config), `/dsh-tts-api/cloud-*` (Cloud key/usage/test), `/dsh-tts-api/notify` (approval-alert queue), `/dsh-tts-api/diagnose` (one-click diagnostics); runs a zero-dependency Edge worker via `node -e` |
162
+ | Client | `lib/client.js` | Web Audio chunk player (sample-accurate joins, `<audio>` fallback) in `shell.overlay` + the UI entries (read-aloud button / auto-read toggle / settings panel); talks to the Host through `fetch` |
163
+
164
+ The TTS worker mirrors [node-edge-tts@1.2.10](https://github.com/SchneeHertz/node-edge-tts):
165
+ `Sec-MS-GEC` query params (ticks rounded to the 5-minute boundary),
166
+ `Sec-MS-GEC-Version=1-143.0.3650.75`, `Path:audio` binary framing, `xml:lang`
167
+ derived from the voice locale, one retry on abnormal (1006) closures. Audio is
168
+ `audio-24khz-48kbitrate-mono-mp3`.
169
+
170
+ ## Edge cases handled
171
+
172
+ - Clicking the read button of the message being auto-read stops it; another
173
+ message's button switches to manual reading.
174
+ - Disabling auto-read never interrupts a manual read; it stops auto reads.
175
+ - A newly completed message (auto on) interrupts the current read; text-less
176
+ messages are skipped; session switches only stop auto reads.
177
+ - Stopping / switching messages **eagerly cancels** the active RVC chunked job on
178
+ the Host, so the local conversion service stops scheduling new chunks and
179
+ releases GPU/memory promptly (no waiting for the lazy GC).
180
+ - Repeatedly reading the same text + voice **reuses the in-session audio cache**
181
+ (no re-synthesis); if the cached backing file was cleaned by the OS, it
182
+ transparently re-synthesizes instead of serving a stale 404 URL.
183
+ - If an Edge voice was removed by the endpoint (`1007 Unsupported voice`), the
184
+ voice is pruned from the picker and the plugin auto-falls back to the default.
185
+ - Audio is **autoplay-unlocked** on the first user gesture (Web Audio context
186
+ resumed + silent clip) so reads aren't silently blocked by browser policy.
187
+ - `Esc` / `S` (outside an input) stops the current read-aloud.
188
+ - Synthesis / playback failures **surface a themed toast** (message read-aloud and
189
+ auto-read no longer fail silently; the preview panel keeps its inline error).
190
+ In RVC mode the error toast carries a one-click **"read with Edge TTS instead"**
191
+ action; with the opt-in toggle **"auto-switch to Edge TTS when RVC fails"** in
192
+ the RVC settings (off by default — RVC is fully local, auto-fallback sends the
193
+ text to Microsoft's endpoint), a failed RVC read silently retries with the RVC
194
+ base voice via Edge TTS and shows a warn toast.
195
+ - **Smart chunking** never splits URLs / emails / decimals / versions ("3.14")
196
+ mid-token — hard cuts slide to word/punctuation boundaries, and a tiny trailing
197
+ sentence merges into the previous chunk instead of reading like a stutter.
198
+ - **Approval voice alerts** (opt-in): the Host subscribes to the session/event
199
+ firehose (`approval/asked` / `approval/decided`), dedupes by approval id, and
200
+ the client polls `/dsh-tts-api/notify?s=N` — the first poll baseline-syncs the
201
+ cursor so a page refresh never replays stale alerts; announcements are silent
202
+ on failure (no error toasts while the agent loops).
203
+
204
+ ## Settings persistence
205
+
206
+ Layered storage:
207
+
208
+ - **Host file** (`~/.dsh/tts-rvc/settings.json`,
209
+ `{ version: 1, rvc: …, index: …, cosy: …, cloud: … }`):
210
+ service-class config — RVC service URL/model/index paths, Index-TTS2 and
211
+ CosyVoice service URLs, Cloud API key (+ optional project ID). Shared across
212
+ browsers, survives browser-data clears and incognito. Served/updated through
213
+ `GET /dsh-tts-api/rvc-config` + `POST /dsh-tts-api/rvc-config-save`
214
+ (and the matching `index-config`, `cosy-config`, `cloud-config` routes;
215
+ legacy `localStorage` values migrate up once, then the file wins).
216
+ - **localStorage** (`dsh-tts-settings`): UI prefs only — voice, auto-read
217
+ toggle, provider, sound tuning, the raw-Markdown toggle, approval-alert and
218
+ remaining RVC prefs. Never stores the service URL / model / index.
219
+
220
+ A "Reset to defaults" button in the settings panel restores defaults and clears
221
+ both layers (best-effort on the Host file).
222
+
223
+ ## Custom voice (RVC)
224
+
225
+ Use your locally trained **RVC model** for voice conversion: switch the TTS
226
+ provider to "自定义音色(RVC)" in the settings panel. **First-time RVC users
227
+ need two things**: a model file (`.pth`) and a running local RVC service — see
228
+ the [RVC Guide](docs/RVC-GUIDE.md) or [User Guide](docs/USER-GUIDE.md) §4.2 for
229
+ macOS/Windows/Linux startup commands. The full story — service startup, panel
230
+ config, gapless chunked playback, compact index, voice-pack registry install,
231
+ portable runtime, settings reference and troubleshooting — lives in the
232
+ **[RVC Custom Voice Guide](docs/RVC-GUIDE.md)**.
233
+
234
+ > Public pack registry example: [rvc-for-tts](https://github.com/1624318455/rvc-for-tts)
235
+ > (设置 → 语音 → 音色包 → registry URL: `https://raw.githubusercontent.com/1624318455/rvc-for-tts/main`).
236
+
237
+ ## Troubleshooting (Edge TTS)
238
+
239
+ - **403 / `Sec-MS-GEC` rejected**: the Edge endpoint protocol or version check
240
+ changed; update `CHROMIUM_FULL_VERSION` / `TRUSTED_CLIENT_TOKEN` inside the
241
+ worker in `lib/index.mjs`.
242
+ - **`1007 Unsupported voice`**: the selected voice was removed from the
243
+ endpoint; pick one from the table above.
244
+ - **No sound**: check system volume, the browser autoplay policy (interact
245
+ with the page once), or the synthesis logs (`[tts]` errors in the `dsh web`
246
+ console).
247
+
248
+ > RVC-specific troubleshooting: [RVC Guide → Troubleshooting](docs/RVC-GUIDE.md#troubleshooting).
249
+
250
+ ## FAQ
251
+
252
+ **Q: Is it big?**
253
+ - Default experience (Edge TTS): the plugin itself is tiny (MB scale) — **no service or model to download**.
254
+ - You only need a local RVC portable package if you want custom voices (RVC). Its size mostly comes from the **bundled offline Python runtime + inference deps + pretrained models**:
255
+ | Platform | Archive | Extracted |
256
+ |---|---:|---:|
257
+ | macOS (Apple Silicon) | ~660 MB | ~1.3 GB |
258
+ | Windows (CPU-minimal) | ~1–2 GB | ~2–3 GB |
259
+ | Windows (with NVIDIA GPU) | ~6 GB | ~7 GB |
260
+ - These are self-contained runtimes; the **full RVC WebUI is 7.8 GB** — we don't ship the WebUI / training / realtime parts this plugin doesn't need.
261
+ - Index-TTS2 / CosyVoice also ship as local bundles (sizes vary by release — see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md) / [CosyVoice Guide](docs/COSYVOICE-GUIDE.md) preparation sections).
262
+
263
+ **Q: Are the dependencies big?**
264
+ - The runtime is heavy but **you don't install anything**: the portable package bundles Python, ffmpeg (Windows) / PyAV (macOS), and all inference deps. Unzip and run — no compile, no env setup.
265
+ - The plugin itself has minimal deps and only loads what it actually uses.
266
+
267
+ **Q: Do I need a local TTS model?**
268
+ - With the default Edge TTS or Cloud TTS: **no** — they synthesize online.
269
+ - With custom voices (RVC): you need **your own** RVC voice model (`.pth`), optionally a `.index`; the pretrained hubert / rmvpe are already bundled — you only provide your trained model.
270
+ - With Index-TTS2 / CosyVoice: no training needed — you provide **reference/prompt audio** (a few seconds of clear speech) to the local bundle and pick it in the panel; see the [Index-TTS2 Guide](docs/INDEX-TTS2-GUIDE.md) and [CosyVoice Guide](docs/COSYVOICE-GUIDE.md).
271
+
272
+ **Q: Is it easy to install?**
273
+ - Install the plugin normally, then for RVC: download the portable package for your platform → unzip → run the launcher (double-click `.command` on macOS, `.bat` on Windows) → drop your `.pth` into `assets/weights` → pick it in the plugin panel.
274
+ - Index-TTS2 / CosyVoice follow the same three steps (bundle → keep its service running → pick a voice in the panel); Cloud TTS only needs an API key pasted into settings. Each provider guide walks through it.
275
+ - No compile, no manual Python/ffmpeg install. Note: **the first macOS launch is slow (tens of seconds)** while macOS scans the extracted runtimes (one-time); later launches take a few seconds.
276
+
277
+ **Q: Do I need a paid API?**
278
+ - No for Edge TTS (free, no API key) and RVC / Index-TTS2 / CosyVoice (fully
279
+ local and free — but each needs its local service package running, see
280
+ Requirements above).
281
+ - Google Cloud TTS is pay-as-you-go and needs your own API key: Chinese
282
+ Standard voices are free for the first 4M chars/month, Wavenet/Neural2/Chirp
283
+ for the first 1M chars/month (local counters; Google Cloud Billing is
284
+ authoritative). See the [Cloud Guide](docs/CLOUD-GUIDE.md).
285
+ - Note: Edge TTS is Microsoft's public client-side, free capability — fine for personal use; check Microsoft's terms for commercial / heavy usage.
286
+
287
+ **Q: Did this modify the DSH core?**
288
+ - No. It's an **independent plugin** loaded through dsh's plugin mechanism. It doesn't touch the DSH main program and can be installed / paused / uninstalled anytime without affecting DSH or other plugins.
289
+
290
+ **Other common questions**
291
+ - **Do I need a GPU?** No — CPU works. For speed you can use Apple Silicon MPS (macOS) or an NVIDIA GPU (Windows, which needs the bigger CUDA torch build).
292
+ - **Privacy?** RVC conversion is fully local — audio never leaves your machine. Edge TTS sends the text-to-read to Microsoft's endpoint for online synthesis (assess which voice before choosing).
293
+ - **Apple Silicon only?** The macOS build is arm64 (M1–M5); Intel Macs would need a separate x86_64 build.
294
+
295
+ ## UI language (i18n)
296
+
297
+ The settings panel has an **Interface language** selector at the top:
298
+ **Auto (follow browser) / 中文 / English**.
299
+ - Default "Auto" follows the browser/system language (Simplified Chinese and
300
+ others → Chinese, everything else → English).
301
+ - Switching applies immediately and is **persisted** to localStorage
302
+ (`dsh-tts-lang`), surviving page reloads.
303
+ - Covers the whole settings panel, bubble/read-aloud buttons, diagnostics,
304
+ voice-pack panel, plus RVC service errors/progress hints.
305
+
306
+ ## Development
307
+
308
+ ```sh
309
+ node tests/smoke.mjs # fake-ctx route registration + real Edge TTS synthesis + audio serve assertions
310
+ npm run test:all # full: smoke + live + patch + i18n + client-load
311
+ ```
312
+
313
+ Hot-reload after editing `lib/` (on Windows a `file:` install is a COPY, not a
314
+ symlink, so the running dsh reads the profile copy):
315
+
316
+ ```powershell
317
+ Copy-Item lib/* $env:USERPROFILE\.dsh\profiles\web\node_modules\@memef1f1y\dsh-plugin-tts\lib\ -Recurse -Force
318
+ # then refresh the browser (bundles are re-read from disk per request; never use pnpm install --force)
319
+ ```
320
+
321
+ ## Known limits
322
+
323
+ - Voice / auto-read toggle / provider / RVC settings are persisted in layers
324
+ (Host file for service config, localStorage for UI prefs — see "Settings
325
+ persistence" above) and survive refresh (see "Settings persistence" above); the
326
+ audio cache itself is in-session only (files live in the OS temp dir, cleaned
327
+ by the OS), so a full restart re-synthesizes the first read of each text.
328
+ - Synthesized audio is written to the OS temp dir and cleaned by the OS.
329
+ - zh/en **layout/visual** fitting (English text is longer; may wrap/overflow; theme
330
+ vars `--dsw-*`) must be eyeballed in the real dsh UI with the plugin loaded — this
331
+ plugin ships no standalone HTML (its UI is slot-injected by the dsh web host), so
332
+ it cannot be headless-screenshotted here (`tests/client-load.mjs` asserts the
333
+ in-memory render only, not real DOM/CSS).
334
+
335
+ ## License
336
+
337
+ MIT