Bundle
dsh-tts
Text-to-speech for dsh web: speaks each assistant reply out loud using Edge TTS neural voices (host bridge + browser player)
- Source
- Vim0x3c
- stars
- 4 stars
- License
- MIT
- Updated
- Updated 4 days ago
Readme
# dsh-tts
[English](README.en.md) | 中文
[dsh web](https://github.com/deepseek-ai/deepseek-harness) 的**语音播报**插件:把每个助手答复的**最终结果**用 **Edge TTS**(微软神经语音)朗读出来,实现开口即答的语音交流。
- **真·Edge TTS**:宿主(Node)端用微软 Edge “大声朗读” 神经语音接口在线合成 MP3,浏览器播放 —— 无需 OpenAI/第三方密钥,免费。握手用**自实现的 RFC 6455 WebSocket**(Node 原生 WebSocket / undici 会过滤微软必需的握手头导致升级被拒,手动握手实测返回 101)。
- **只读最终结果**:中间步骤、工具调用说明不读;每个回合只朗读收尾那条最终答复;连续多回合只读最新一条。长回复自动按句子分段串行朗读。自动朗读失败会降级到浏览器本地 `speechSynthesis`(离线也能出声)。
- **音色/语速**:内置 `zh-CN-XiaoxiaoNeural` 等 20+ 个 Edge 神经音色,滑块调语速 (0.5×–2×)。
- **喇叭开关**:输入框工具排的喇叭按钮(悬停有提示)快速开关「自动朗读新回复」;关闭时立即中断当前朗读。设置里与「自动朗读新回复」联动。
- **审批提示**:遇到「需要审批」时朗读“需要审批”,可单独关闭;可自定义审批提示音(预设「叮/哔哔/咚」或用 Web Audio/上传 mp3/wav/ogg ≤1MB,选定即时试听)。
- **完全本地、零运行时依赖**:Edge 协议用 Node 内置 API 原生实现,插件本体不含任何第三方 npm 依赖,离线也能安装。
`dsh-plugin` topic: (https://github.com/topics/dsh-plugin)
> 默认音色 `zh-CN-XiaoxiaoNeural`(晓晓)。如需更多官方音色,自行在 `src/voices.ts` 里追加 Edge `ShortName` 即可。
## 设置界面

## 安装
> 前置要求:dsh 的应用闭包需包含插件的 `@deepseek-ai/dsh-*` peer 包——即任何带 `@deepseek-ai/dsh-web-app` bundle 的部署(`dsh web` 官方 profile 都满足)。
### 方式一:本地构建 tarball 后安装(最常用)
> 本项目当前以**源码仓库**形式发布,没有已构建的 release `tgz`。你要先在仓库里构建出 `dsh-tts-0.1.0.tgz`,再通过它安装。
1. **克隆/进入仓库并构建**:
```sh
git clone https://github.com/Vim0x3c/dsh-tts.git dsh-tts
cd dsh-tts
pnpm install
pnpm build # tsdown:产出 lib/index.js、lib/client.js 等
npm pack # 生成 dsh-tts-0.1.0.tgz
```
> 若你只想在本机用,也可以直接在仓库根执行 `pnpm build` 拿到 `lib/`;但**安装到 dsh 建议用 tarball**(`npm pack` 生成)。
2. **安装到 web profile**:
```sh
dsh plugin --profile web add -w ./dsh-tts-0.1.0.tgz
```
> `-w` 标志是**必须**的:每个 profile 都带一个 `pnpm-workspace.yaml`,pnpm 会把 profile 目录当作 workspace 根,裸 `add` 会报 `ERR_PNPM_ADDING_TO_ROOT`。
3. **重启 `dsh web`**(宿主端会在启动时加载插件):
```sh
dsh web # 或 dsh --profile web
```
4. **验证安装成功**:
```sh
# ① 插件已在组合配置里(应看到 - id: dsh-tts)
dsh --profile web --dump-config | grep dsh-tts
# ② 宿主桥已起来(应返回 200 {"ok":true})
curl http://127.0.0.1:8765/health
```
### 方式二:git URL 安装(不推荐)
```sh
dsh plugin --profile web add github:Vim0x3c/dsh-tts
```
> ⚠️ 不推荐:从 git 安装取到的是**源码**而非构建好的 `lib/`,且插件的 peer 包未发布到 npm,git 安装通常无法构建或解析它们。请先本地构建 tarball 再按方式一安装。
### 卸载 / 重装
```sh
dsh plugin --profile web remove dsh-tts # 卸载
dsh plugin --profile web add -w ./dsh-tts-0.1.0.tgz # 重装(覆盖)
```
## 使用
1. 打开 dsh web 的 **设置 → 语音播报**(见上方截图)。
2. 打开 **自动朗读新回复**,先点 **试听音色** 确认能连通 Edge(首次会看到“正在朗读…”)。
3. 之后每次助手给出**最终答复**,就会以所选音色自动朗读。
- **喇叭开关**:输入框工具排里的喇叭按钮(悬停有提示),点一下开/关「自动朗读新回复」,关闭时立刻中断当前朗读。
- **自动朗读新回复**:唯一总开关;关掉则助手答复不会自动读,但**试听音色**仍可手动触发。
- **审批提示朗读**:遇到“需要审批”时语音提示,独立开关;可再设置「审批提示音」(预设或上传,选定即时试听)。
- **停止朗读**:随时打断当前播放。
> **自动播放策略**:浏览器通常要求页面有过一次用户交互后才允许自动播声音。因为你只有在发消息后才会收到答复,所以一般没问题;若仍被拦截,先在设置里点一次「试听音色」即可解锁。
> 语音输入(话筒/STT)暂未包含:浏览器 `SpeechRecognition` 只在 Chrome/Edge 可用、Safari 不支持,且 dsh 无内置 STT。若需要语音输入,可参考 [dsh-plugin-voice-input](https://github.com/Hjay1101/dsh-plugin-voice-input) 或 [dsh-voice](https://github.com/Jesse-njx/dsh-voice)。
## 开发
```sh
pnpm install
pnpm build # tsdown:产出 lib/index.js(宿主)、lib/invariant.js、lib/client.js(浏览器)
pnpm test # vitest:跑单元/回归测试
```
构建自包含(tsdown + lightningcss),无需 monorepo 检出。`prepare` 运行同一构建,因此允许的 git 安装也会产出产物。
> 本仓库本地 `node_modules` 复用了 `dsh-skin-appearance` 的 pnpm store,是为了离线类型检查/构建;发布 tarball 时 peer 包不必打成依赖(它们由 dsh 应用闭包在运行时解析)。
## 工作原理
- **宿主一半**(`lib/index.js`):启动一个仅绑定 `127.0.0.1` 的小型 HTTP 服务(探测端口 8765–8780),路由:
- `GET /health` —— 桥是否活着;
- `POST /synthesize` —— 传入 `{ text, voice, rate }`,走原生 Edge 协议合成 MP3 返回。
- CORS 已加固:仅反射白名单内的 dsh web 源,未知网页 Origin 直接 403;无 Origin(命令行)照常放行。
Edge 协议(`src/edge/`)即 Edge 浏览器“大声朗读”所用接口:`Sec-MS-GEC`(SHA-256 FILETIME)+ `Sec-MS-GEC-Version` 鉴权、浏览器指纹握手头(`Origin`/`User-Agent`/`Cookie: muid`)、`speech.config` → SSML 两条消息、二进制帧按「2 字节头长 + 内嵌 `Path: audio` 头 + MP3」解析拼装。**WebSocket 用自实现的 RFC 6455 手动握手**。零第三方依赖。
- **浏览器一半**(`lib/client.js`):通过 `ctx.sessions` 订阅当前会话,识别每个回合的最终答复、只读最新一条、长文分段串行播放,`fetch` 宿主桥取回 MP3 用隐藏 `<audio>` 播放。播放用“代次 token + AbortController”保证停止/打断竞态正确,停止也会一并静音审批提示音。**朗读失败自动降级到浏览器 Web Speech API**(`speechSynthesis`)。**设置项持久化在浏览器 localStorage**(`dsh-tts.settings`),因为 dsh web 宿主只向浏览器暴露固定白名单的 settings 命名空间,独立插件无法扩展(见 `api-proxy.ts` 的 `WEB_SETTINGS_NAMESPACES`)。
## 已知限制
- **Edge 云合成需要网络**:宿主须能访问 `speech.platform.bing.com`。确认前请先用设置面板“试听音色”;若返回 `could not connect` 或 403,说明本机到 Edge 端点被网络/区域/防滥用机制拦下——此时**会自动改用浏览器本地 Web Speech 语音**,功能仍可用。
- **`Sec-MS-GEC` 令牌已验证对齐**当前 `edge-tts` 算法(SHA-256 FILETIME + `Sec-MS-GEC-Version`)。若微软再次轮换算法,改 `src/edge/token.ts` 一处即可(“试听音色”会立刻暴露 403)。
- **只读当前会话**:自动朗读跟随设置里正在查看的会话;后台会话的答复不会朗读。
- **进程内桥**:桥服务随 `dsh web` 宿主生命周期启停;停掉 dsh web 即关闭。
- **语音输入不在本插件内**(见上文“使用”中的说明)。
## License
MIT
Install
dsh plugin --profile web add github:Vim0x3c/dsh-tts
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-tts from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.