dsh-tts
English | 中文
dsh web 的语音播报插件:把每个助手答复的最终结果用 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里追加 EdgeShortName即可。
设置界面

安装
前置要求:dsh 的应用闭包需包含插件的
@deepseek-ai/dsh-*peer 包——即任何带@deepseek-ai/dsh-web-appbundle 的部署(dsh web官方 profile 都满足)。
方式一:本地构建 tarball 后安装(最常用)
本项目当前以源码仓库形式发布,没有已构建的 release
tgz。你要先在仓库里构建出dsh-tts-0.1.0.tgz,再通过它安装。
克隆/进入仓库并构建:
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生成)。安装到 web profile:
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。重启
dsh web(宿主端会在启动时加载插件):dsh web # 或 dsh --profile web验证安装成功:
# ① 插件已在组合配置里(应看到 - id: dsh-tts) dsh --profile web --dump-config | grep dsh-tts # ② 宿主桥已起来(应返回 200 {"ok":true}) curl http://127.0.0.1:8765/health
方式二:git URL 安装(不推荐)
dsh plugin --profile web add github:Vim0x3c/dsh-tts
⚠️ 不推荐:从 git 安装取到的是源码而非构建好的
lib/,且插件的 peer 包未发布到 npm,git 安装通常无法构建或解析它们。请先本地构建 tarball 再按方式一安装。
卸载 / 重装
dsh plugin --profile web remove dsh-tts # 卸载
dsh plugin --profile web add -w ./dsh-tts-0.1.0.tgz # 重装(覆盖)
使用
- 打开 dsh web 的 设置 → 语音播报(见上方截图)。
- 打开 自动朗读新回复,先点 试听音色 确认能连通 Edge(首次会看到“正在朗读…”)。
- 之后每次助手给出最终答复,就会以所选音色自动朗读。
- 喇叭开关:输入框工具排里的喇叭按钮(悬停有提示),点一下开/关「自动朗读新回复」,关闭时立刻中断当前朗读。
- 自动朗读新回复:唯一总开关;关掉则助手答复不会自动读,但试听音色仍可手动触发。
- 审批提示朗读:遇到“需要审批”时语音提示,独立开关;可再设置「审批提示音」(预设或上传,选定即时试听)。
- 停止朗读:随时打断当前播放。
自动播放策略:浏览器通常要求页面有过一次用户交互后才允许自动播声音。因为你只有在发消息后才会收到答复,所以一般没问题;若仍被拦截,先在设置里点一次「试听音色」即可解锁。
语音输入(话筒/STT)暂未包含:浏览器
SpeechRecognition只在 Chrome/Edge 可用、Safari 不支持,且 dsh 无内置 STT。若需要语音输入,可参考 dsh-plugin-voice-input 或 dsh-voice。
开发
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
No comments yet. Be the first to write one.