DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

dddmxza /

dddmxza/dsh-mimo-voice

Verified

Xiaomi MiMo TTS voice plugin for DeepSeek Harness — speaks a line through your local speakers, with voice design, preview and approval alerts built in.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@ef0a158f

dsh-mimo-voice

DeepSeek Harness 的语音输出插件。调用 TTS 服务合成语音,写入 audio/ 目录,由当前浏览器页面播放,也可经 ffplay 从本机音频设备播放或推送至远端播放端点。当前支持小米 MiMo 与 Breeze Blue 两家服务商。

功能:

  • 通过系统提示词注入,使模型在每次回复时调用 speak 输出语音
  • 审批请求挂起时播放提醒语音
  • 设置面板中配置 API 密钥、音色描述,并支持试听与样本固化

安装

pnpm --dir C:\Users\<user>\.dsh\profiles\desktop add link:D:/path/to/dsh-mimo-voice

随后在 profile 的 package.json 中将 dsh-mimo-voice 加入 dsh.profile.bundles,重启桌面端。

依赖 ffplay / ffmpeg,默认查找 C:\ffmpeg\bin\,也可通过环境变量 FFPLAY_PATH / FFMPEG_PATH 指定。默认的页面播放不需要这两者;页面未加载时回退才使用 ffplay,音色固化与远端推流使用 ffmpeg。

配置

打开 设置 → 插件 → 语音输出。面板分为 接入、音色、输出、行为 四组,修改后点击底部「保存」写入 config.json;「还原」丢弃未保存的修改。顶部状态标记依次表示密钥是否已配置、当前服务商、语音输出是否启用、输出设备。

配置项 说明
服务商 语音合成的提供方。可选 mimo(小米 MiMo)与 breeze(Breeze Blue),新增服务商需在 lib/engine.js 注册
音色 ID 仅 Breeze Blue 使用。该服务商的音色须先在平台生成并保存,此处填写其 voice_id
语言码 仅 Breeze Blue 使用。ISO 639-1 两字母代码,决定发音口音与语言模型,默认 zh
指导强度 仅 Breeze Blue 使用。对应 guidance_scale,取值 1–10,越高越贴合音色描述;留 0 采用服务端默认
音色描述 生成音色所用的自然语言描述。voicedesign 模型每次调用重新生成音色;试听后可将结果固化为克隆样本
试听文本 试听时合成的文本内容
当前音色 显示为「已固化」或「为每次生成」,固化后可切回生成模式
输出设备 local 在当前浏览器页面播放,board 推送远端端点,both 两路并行
语音推送接口 远端播放服务的基址,默认 http://192.168.31.123
推送失败回退本机 远端不可达时改由本机输出,避免该句完全无声
推送前响度归一 推送前将均值提到 -16 LUFS、峰值锁在 -3 dBTP,远端增益保持 100。流式路径改用单遍放大加限幅,见「远端播放」
启用语音输出 总开关。开启时注入提示词规则且 speak 正常合成;关闭时既不注入规则,speak 也直接拒绝,不发起 TTS 请求
审批挂起时提醒 审批请求挂起时播放提醒语音
提醒语句 候选提醒语句列表,逐条添加与删除,播放时随机选取;列表为空时使用出厂语句。句首可加 (语速快,很焦急) 形式的语气标签
API 密钥 服务商 API 密钥,以明文存储于插件根目录 .env,按服务商分键位:MIMO_API_KEY、BREEZE_API_KEY

页面播放

output 为 local(默认)时,音频在浏览器页面内播放:宿主把待播句排入队列,页面以最长 20 秒的长轮询请求 /api/dsh-mimo-voice.queue 取句,再经 AudioContext 播放;both 时页面与远端并行。这种方式不依赖本机安装任何播放器。

页面播放分两条路。引擎实现了 openStream() 且输出为 local / both 时走流式:宿主请求服务商的流式端点,每收到一块裸 PCM 就转给页面,页面按块建 AudioBuffer 首尾相接排到声卡上,因此第一块到达即可出声,无需等待整段合成。其余情况走整段:合成完成、落盘、页面用 decodeAudioData 解整个文件。两种方式落盘留档的行为一致。

本机输出不再单设页面选项:音频直接入队,由页面取走。若客户端未加载起来(宿主版本更新而页面仍在用旧 bundle),本机输出回落 ffplay,并在日志输出一行提示。浏览器要求 AudioContext 经用户交互方可启动,页面首次点击或按键时会自动恢复。

远端播放

output 为 board 或 both 时,合成的音频经 ffmpeg 转为 16 kHz / 16 bit / 单声道裸 PCM,以 Transfer-Encoding: chunked 请求体 POST 到远端端点的 /say?sr=16000。远端收到一块即写入 I2S,因此第一块到达即可出声。该请求的耗时等于音频时长(32 KB/s 为实时速率),8 秒语音约需 7.5 秒返回;宿主不等待其返回,speak 调用在推送开始后即结束。ffmpeg 转码约 100 ms,不构成瓶颈。

流式路径的响度处理使用单遍放大加限幅:volume=1.8,alimiter=limit=0.72:level=disabled,峰值约 23600,落在远端软限幅膝点 24000 之下。两遍 loudnorm 需攒满约 3 秒才开始输出,与流式目标冲突,故流式路径不采用。

远端固件需支持 /say 端点接受 chunked 请求体,并支持 I2S 全双工(收发共用 I2S_NUM_0,输出期间丢弃麦克风数据以避免回声自激)。

结构

三个职责分层,互不越界:

层 位置 职责
协议 lib/engine.js 向服务商请求音频,返回音频字节与音色元数据。换服务商只改这一个文件
音色 lib/engine.js 的 voiceOf() 决定用哪副声音:design 每次按描述生成,clone 使用固定样本
交付 lib/index.js 音频落盘至 audio/,按 output 送往页面队列、本机 ffplay 或远端 /say

新增服务商时,在 lib/engine.js 中实现 render(text, cfg, opts) 并导出 { bytes, ext, mime, spoken, voice },再注册进 ENGINES。index.js 无需改动,config.json 的 provider 字段指定当前使用项。

实现

插件不解析、不筛选取要朗读的文本。它向系统提示词注入一个 section,声明本机具备语音输出能力,要求模型在每次回复时调用 speak 输出一句,语气以 text 开头的括号表达,正文不出现括号与记号。

输出开关同时控制两处:

  • 提示词:开启时该 section 返回规则正文;关闭时返回空字符串,本轮提示词不含该节。
  • 工具:speak 的 execute 在入口处读取开关,关闭时返回失败状态且不发起 TTS 请求。

注入使用 ctx.systemPrompt.section({ name, order: 3250, interpolate: false, text })。text 传入函数而非字符串,每次组装提示词时读取 config.json,因此切换开关无需重启 DSH。interpolate: false 用于避免规则正文中的花括号被提示词引擎插值。order: 3250 使该 section 位于提示词末尾,靠近生成阶段,避免被前文稀释。

规则正文定义于 lib/index.js 的 SPEAK_POLICY。

语气标签

以下是 TTS 服务本身支持的语法,供手动指定语气时参考;插件注入的系统提示词不再要求使用标签,speak 的文本按纯文本合成。

按 MiMo 官方文档(speech-synthesis-v2.5)的音频标签规范:标签置于 assistant 文本开头、紧接正文首字,半角 ()、全角 ()、方括号 [] 均可,多个标签可置于同一对括号内。

标签应使用正向、可执行的描述,不使用否定式。模型对否定词不敏感,尾音不抬、别拖长 等写法可能产生反向效果;应改为 尾音收住往下落、语速稍慢 等正向表述。

优先使用官方词表内的词项:

  • 整体语调:温柔 / 高冷 / 活泼 / 严肃 / 慵懒 / 俏皮 / 深沉 / 干练 / 凌厉
  • 复合情绪:怅然 / 欣慰 / 无奈 / 愧疚 / 释然 / 嫉妒 / 厌倦 / 忐忑 / 动情
  • 句中标签:气声 / 叹气 / 深呼吸 / 轻笑 / 冷笑 / 哽咽 / 颤抖 / 鼻音 / 不耐烦 / 心虚 / 撒娇 / 小声 / 提高音量喊话

不应在标签中使用音色词(磁性 / 醇厚 / 清亮 / 空灵 / 稚嫩 / 苍老 / 甜美 / 沙哑 / 醇雅)。音色由 voiceDesign 定义,而 voicedesign 模型每次调用重新生成音色,标签中出现音色词会导致该次调用的基础音色一并改变,造成音色漂移。

voiceDesign 本身已覆盖长期设定:音色质感、语速、情绪基调均属官方支持的维度。标签仅用于表达与常规不同的临时调整,避免与音色描述产生互斥指令。如需完全固定音色,使用 voiceMode: 'clone' 并提供参考样本。

voicedesign 模型不支持唱歌模式,也不支持预置音色与音色复刻,后者需使用 mimo-v2.5-tts。

版本说明

0.3.0 及更早版本由插件监听 assistant/message 事件并截取文本朗读,实现中包含 pickLine 函数与 【念】 记号。0.4.0 起移除该链路,改为提示词注入方案。0.4.1 起输出开关由「仅控制提示词注入」改为总开关,关闭时 speak 同样不可用。0.5.0(待发布)增加输出设备(本机 / 远端 / 同时)、远端 chunked 流式推送、协议层拆分与 Breeze Blue 服务商、设置面板重做、页面内流式播放。

API

方法 路径 说明
GET /api/dsh-mimo-voice.config 读取配置,密钥仅返回 hasKey 布尔值
POST /api/dsh-mimo-voice.config 写入配置
POST /api/dsh-mimo-voice.preview 试听,body 可含 text / voiceDesign
POST /api/dsh-mimo-voice.pin 将最近一次试听结果固化为音色样本
POST /api/dsh-mimo-voice.speak 朗读指定文本
POST /api/dsh-mimo-voice.stop 中止当前播放
GET /api/dsh-mimo-voice.queue 页面取句,since 为已取序号,wait 为长轮询毫秒数
GET /api/dsh-mimo-voice.audio 页面取音频文件,f 为 audio/ 下的文件名
GET /api/dsh-mimo-voice.stream 页面取流式音频,id 为句序号。每句只可被取一次,返回裸 PCM 并附 X-Sample-Rate / X-Bits / X-Channels

工具定义:speak(text)。

限制

  • voicedesign 与 voiceclone 每次调用按描述重新生成音色,结果不完全一致。需要固定音色时应使用克隆模式。
  • 小米 MiMo 为非流式接口,音频一次性返回。Breeze Blue 支持流式端点,页面播放与远端推送均为边合成边送出。
  • 流式路径下 ffmpeg 只做单遍放大加限幅,不做两遍响度归一,因此句与句之间的平均电平会有小幅差异;整段路径仍使用 loudnorm。
  • TTS 接口限流 RPM 100,超出返回 429,需等待后重试。

测试

node test/smoke.mjs          # 仅验证注册,不发起网络请求
node test/smoke.mjs --speak  # 实际合成并播放
—/ 5

No ratings yet

Verified DSH bundle

Commit ef0a158fa268

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout