前言¶
在 DeepSeek Harness(DSH)里做智能体对话时,长回答往往要盯着屏幕读。社区里也有用 SKILL 走 Edge TTS 的做法,例如 multilingual-tts-audio:每次都要 uv run --with edge-tts python …,等整段 MP3 写完,还要主动触发,和模型输出节奏对不上。
下面介绍插件 lemonhall/dsh-tts-reader(维护者 lemonhall,分类为联网工具):常驻 DSH 进程内,监听模型原始输出流,逐句向 Edge TTS 拉取音频,页面用 Web Audio 连播;默认用小艺(zh-CN-XiaoyiNeural)朗读,并支持重读任意一条历史回答。
这是什么¶
dsh-tts-reader 是 DSH 的 Web 客户端注入型插件(package.json 中 meta.title 为「朗读回答(小艺)」)。宿主侧用零依赖 Edge TTS 客户端合成 MP3,页面侧负责播放与开关;不替换 DSH 核心,通过 Cordis patch 挂载路由并监听 agent/assistant-stream。
社区目录页:https://www.skillhub.cn/plugins/lemonhall/dsh-tts-reader(SkillHub 为独立插件广场,与 DeepSeek / 幻方无官方从属关系)。源码与说明:https://github.com/lemonhall/dsh-tts-reader。当前资料中版本为 0.1.0,许可证 MIT。
核心功能¶
两个入口,两条队列¶
| 位置 | 作用 |
|---|---|
| 输入框右侧喇叭 | 整个会话的实时朗读开关(默认开),状态存在 localStorage |
| 每条回答下方喇叭 | 在「显示 / 复制 / 点赞 / 用量 / 时间」一行,重读这一条;再点停止 |
实时朗读与「重读某条」是独立队列。点重读会临时接管扬声器;读完自动把实时朗读接回,从下一句继续,不补播期间错过的内容。
边写边念的数据路径¶
模型仍在输出时,插件已从原始流取文,比 DOM 更早:
agent/assistant-stream GET /dsh-tts/tail?session=…&since=…
(模型正在写的原文) (base64 MP3,按句游标拉取)
│ ▲
▼ │
lib/index.js ──► lib/feed.js ──► lib/edge-tts.js
宿主半边 逐句队列 零依赖 Edge TTS 客户端
│
Session.snapshotEvents() ────────────────┤
(某条历史回答的正文) GET /dsh-tts/message?session=…&id=…&since=…
│ │
└──────────────► lib/feed.js ─────────┤
│
lib/client.js ──┘
页面半边:Web Audio 无缝连播 + 两个开关
合成放在宿主侧,是因为 Edge 朗读服务要求浏览器类 User-Agent 才会 WebSocket 101 升级,而页面侧 WebSocket 无法自定义请求头。页面每 400 ms 用游标拉取一次;没有听众的会话不会触发合成。
重读某条的正文来自 ctx.sessions.get(id).snapshotEvents() 里 assistant/message 事件的 stream(可见正文,不含推理与工具调用)。被查看的会话在内存中存活时,整段可见历史都可读,不受插件安装时间限制。
念给人听的内容¶
朗读的是口语化文本,不是屏幕上的 Markdown 原文:
- 围栏代码块整块跳过;行内代码保留字面值
- 表格单元格用「,」连接,分隔行不念
- 链接只念文字,裸 URL 念作「链接」
- 标题、加粗、引用、列表符号等标记去掉
- 推理过程与工具调用参数不念
安装与启用¶
SkillHub 目录页未给出单独的 dsh plugin … 一行命令,而是让 Harness 读取后端安装计划后执行。在目录页使用「发送给 DeepSeek Harness 安装」或「复制安装提示词」,向当前 DSH 会话说明要安装的插件标识即可,例如:
请安装 DSH 插件 lemonhall/dsh-tts-reader。先读取后端安装计划再执行安装。
(完整提示词以目录页「复制安装提示词」为准。)
安装前建议自行阅读 GitHub 仓库源码与 MIT 许可证。插件在 当前 DSH 进程权限 下运行,并会 联网 访问 Edge TTS 服务。
启用后无需额外命令:输入框右侧喇叭默认开启实时朗读。若要在宿主侧整体关闭能力,可改配置(见下);不要用 plugin_manager set_plugin 反复关开本插件——README 实测会出现路由仍在、但 agent/assistant-stream 监听已停、实时朗读静默失效的半死状态。临时不想听,用输入框喇叭即可。
配置¶
在 $DSH_HOME/profiles/desktop/cordis.patch.yml 里找到 dsh-tts-reader 条目的 config(插件未导出 Config schema,Cordis 会把整块 config 交给 apply):
| 键 | 默认 | 说明 |
|---|---|---|
enabled |
true |
宿主侧总开关 |
voice |
zh-CN-XiaoyiNeural |
Edge TTS 短名,启动时向官方声音目录核对 |
rate / volume / pitch |
+0% / +0% / +0Hz |
合成参数 |
maxPerRequest |
3 |
每次拉取最多返回几句 |
改 lib/client.js 后 刷新页面(Ctrl+F5)即可;改 lib/index.js、lib/feed.js、lib/edge-tts.js 等宿主模块 必须重启应用。README 注明:plugin_manager 关开条目不能让宿主半边热重载,改宿主代码一律按需重启预期。
典型用法¶
- 正常与助手对话:模型流式输出时,默认逐句播放小艺语音。
- 暂时关闭:点输入框右侧喇叭;偏好会写入
localStorage。 - 重听某条回答:点该条下方喇叭;再点一次停止。重读结束后实时朗读从下一句恢复。
- 换声音或语速:改
cordis.patch.yml中voice、rate、volume、pitch,重启 DSH 使宿主配置生效。
维护者在仓库内提供自测脚本(需联网的用例需能访问 Edge TTS):
cd E:\development\dsh-tts-reader
node test/feed.mjs # 逐句队列(纯离线)
node test/client-load.mjs # 客户端加载(纯离线)
node test/host-e2e.mjs # 宿主端到端(需联网)
node test/smoke.mjs # 语音目录 + 合成 + 文本清洗(需联网)
调试宿主 WebSocket 时可设环境变量 DSH_TTS_DEBUG=1 打印帧级日志。
适用场景与注意¶
适合:希望在 DSH Web 对话里 hands-free 听回答、且能接受 Edge TTS 联网合成的开发者;需要边生成边听、而不是等整段 MP3 的场景。
注意:
- 依赖 Edge 在线服务;README 记录了
User-Agent、SSML 语音全名、二进制帧格式等协议细节,自行改lib/edge-tts.js时需对照说明,避免 403 或静默断连。 - 分类为联网工具:安装前确认网络策略与源码行为。
- 与 SKILL 方案相比,优势在于进程内常驻、逐句流式、默认跟随助手输出;代价是绑定 DSH 插件与 Cordis 部署方式,而非任意 Python 脚本。
结尾¶
dsh-tts-reader 把助手回答默认用小艺朗读,实时流与历史重读分开排队,宿主合成、页面拉取播放,适合在 DSH 里边写边听。进一步了解请访问目录页 skillhub.cn/plugins/lemonhall/dsh-tts-reader 与 GitHub 仓库 github.com/lemonhall/dsh-tts-reader。