dsh-breeze-speak:用 Breeze TTS 流式朗读 DSH 每轮回复的首句

前言

在 DeepSeek Harness(DSH)里盯着流式文字看,眼睛还是要跟字走;如果等整条回复写完再丢给普通 TTS,往往还要多等 2 秒左右才听到第一个音节。常见做法是整段合成 mp3 再用 <audio> 播放,首声被压在「全文生成 + 编码完成」之后。

下面介绍社区插件 dsh-breeze-speak(维护者 rirtue):挂在宿主 llm/stream 钩子上,第一句一凑齐就向 BreezeBlue(Breeze TTS 2)发起合成,走 /stream 拿 PCM 裸流,用 Web Audio 边收边播。资料里实测首包大约 0.55–1.3 秒,相对「等整段 mp3」的 2.1–2.8 秒,首声能落在模型还在吐后面文字的时间段里,体感上约 0.6 秒出声。默认只念回复开头第一句,也是为了控制 Breeze 积分消耗。

这是什么

dsh-breeze-speak 是一个 DSH 插件(npm 包名 dsh-breeze-speak,当前资料中的版本 v1.0.1,MIT 许可证)。分类上落在 SkillHub 的「模型推理」条目;GitHub 星标为 1。它解决的问题很具体:把每轮模型回复用指定音色念出来,且尽量不让「等 TTS」拖慢你听到第一句话的节奏。

插件按 DSH 惯例拆成宿主半边(index.js)和网页半边(client.js),并通过 cordis.patch.yml 以 id: breeze-speak 写入 profile 配置树。

核心功能

流式触发,不等整段回复

  • 挂住宿主 llm/stream 洋葱中间件,随模型增量累积文本。
  • 每当有新的 text delta,就检查是否已经凑齐第一句(句号、叹号、问号、分号、省略号或换行等)。
  • 第一句一完整就立刻发起合成,而不是等 finally 里整条回复结束。

默认只念第一句

配置项 firstSentenceOnly 默认为 true,只朗读回复开头第一句;可在 ~/.dsh/breeze-speak.json 里关掉,以念更多内容(会多耗 Breeze 积分)。

文本清理与其它插件隔离

送给 Breeze 前会剥掉代码块以及 {}、[]、【】 等标记,避免被逐字念成「左花括号」。同时会跳过由其它插件发起的模型调用(例如返回 JSON 的心情判定),避免把别家插件的 JSON 串进朗读。

PCM 流式播放

走 Breeze 的 /stream 端点,以 SSE 推送 PCM 帧;网页半边 drain 到 Web Audio 时间轴上连续播放,而不是等整段 mp3 编完。

设置页:Key 与在线音色

设置入口为「设置 → Breeze 朗读」:

  • 填写 Breeze API Key(形如 brz_...),保存后立即生效,无需重启。
  • 浏览在线音色:按名字 / 语言 / 性别 / 来源筛选、分页;「▶ 官方试听」播 Breeze 自带预览(免费);「念一句」用该音色试合成(耗少量积分,不改变已保存音色);「选为我的音色」保存默认 voiceId。

设置页只暴露 key 和音色选择器;enabled、firstSentenceOnly、maxChars、instructions 需在配置文件里改,并真正退出桌面应用再开才生效(插件主代码不热重载)。

组成与依赖

文件 作用
package.json 声明 dsh.bundle.patch、dsh.client、入口
cordis.patch.yml 插入 profile(id: breeze-speak)
index.js 宿主:apply(ctx)、注册路由、钩住 llm/stream
client.js 网页:window.__ModuleLoader__.load、设置槽位、播放

前置条件(来自 README):

  1. Node >= 22(DSH 自带运行时满足即可)。
  2. DSH 引擎 >= 0.2.1-rc.2(见 package.json 的 engines.dsh)。
  3. 有效的 BreezeBlue API Key。

API Key 与音色

Key 三种来源,优先级:设置页 > 环境变量 BREEZE_API_KEY > ~/.dsh/.credentials.yaml 里的 refs.BREEZE_API_KEY。设置页点「清空」会回退到后两者。Key 在每次合成 / 拉音色时动态解析,保存后不用重启。

默认示例音色为 voc_u3nxkd5578wc;建议在设置页「在线音色」里从你账号可用的音色里选一个(例如输入名字 →「拉取」→ 试听 →「选为我的音色」)。

拉音色与合成都会访问 api.breeze.blue(发送文本与 key)。明文 key 不下发到浏览器;网页半边只收 PCM 帧和打码后的 key 尾号。

配置

配置文件路径:~/.dsh/breeze-speak.json(不存在则用默认;设置页保存 key 或音色时也会写入此文件)。

{
  "enabled": true,
  "firstSentenceOnly": true,
  "maxChars": 120,
  "voiceId": "voc_u3nxkd5578wc",
  "instructions": "用傲娇又有点心虚、软软的语气念,句尾轻轻上扬再收回去。",
  "apiKey": ""
}
  • 改 key 或 voiceId:设置页保存即可,立即生效。
  • 改 maxChars、instructions、firstSentenceOnly、enabled:编辑上述文件后完整重启 DSH 桌面应用。

安装与启用

SkillHub 目录页与 GitHub 仓库均将该插件标识为 rirtue/dsh-breeze-speak,包已发布到 npm(publishConfig.registry 为 https://registry.npmjs.org)。已抓取资料中未给出固定的 dsh plugin add … 单行命令,安装时请按你当前 DSH 版本的插件安装流程,从 SkillHub 插件页 或 GitHub README 的说明操作;在安装前建议阅读源码与 MIT 许可证,并确认插件以 当前 dsh 进程权限运行。

启用后:

  1. 打开「设置 → Breeze 朗读」,粘贴 brz_... 并保存。
  2. 拉取并选定默认音色,必要时用「念一句」试听。
  3. 正常对话;默认会在第一句出现后自动发起朗读。

宿主 HTTP 路由(前缀 /dsh-breeze-speak/)

仅供理解插件边界,日常通过 UI 即可:

方法 路径 说明
GET /stream SSE:推送 pcm 帧,随后 pcm-end 或 error
GET /state 返回 enabled、voiceId、keyed、keyMasked 等
POST /config 保存/清空 API Key
GET /voices 代理 Breeze 音色库(page 从 1 起,page_size 等)
GET /preview-url?url=... 代理官方预览 mp3(仅允许 https://r.breeze.blue/)
POST /voice 保存 voiceId
POST /preview 即时合成一句试听

每个 handler 先做 准入围栏(ctx.connection.requestRejection):要求已认证的存活 Peer,否则 401/403。因此 shell 里裸 curl 通常无法访问;请用设置页或带 API token 的方式。写操作还会校验 Origin / sec-fetch-site 防跨站。

适用场景与注意

适合谁

  • 长时间用 DSH 对话、希望少盯屏或边做别的事边听首句结论的开发者。
  • 已有 BreezeBlue 账号、能接受按句/按字消耗积分,且愿意自己挑音色、写 instructions 语气的人。

注意

  • 默认只念第一句:长回答的后续内容不会自动全念,除非你改配置并接受更高积分消耗。
  • 插件会调用外网 TTS;除 Breeze API 外,资料未描述其它出站流量,但 key 与文本会发往 api.breeze.blue。
  • 社区目录 SkillHub 与 DeepSeek / 幻方无官方从属关系;插件同理为社区维护,使用前请自行审计代码。

结尾

dsh-breeze-speak 把「第一句写完」和「Breeze PCM 流式合成」绑在 llm/stream 上,用 Web Audio 压低首声延迟,并在设置页完成 Key 与上万在线音色的管理。若要查看元数据或提 issue,见 SkillHub 目录页 与 GitHub:rirtue/dsh-breeze-speak。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye