dsh-ears-prosody
Manifest validLocal offline prosody analysis for DeepSeek Harness: reports how something was said — speed, pitch, pauses, energy — alongside the transcript.
dsh-ears —— 给 DSH 加一双耳朵
把音频变成**「怎么说的」,而不只是「说了什么」**。
它能做什么
一段录音丢进来,回你一份结构化的**「怎么说」**:语速、停顿结构、音高起伏、句尾走向、力度变化、唤醒度——全部本地离线计算,不联网、不要 key。
别人做不到什么
插件市场里的语音插件,几乎都在做两件事:把话变成字(转写 / 听写)和把字变成话(朗读 / TTS)。 这一层做的是第三件事:这话是怎么说出来的。
转写天生会把语气丢掉——停顿、重音、犹豫、句尾是扬起还是沉下去,全在变成文字的那一刻蒸发了。 而这些恰恰是文字里没有的信息:同样一句「哦」,是敷衍还是松了口气,靠的就是它们。
一句话:别的插件处理内容,这个插件处理「内容之外」。
为什么需要它
DSH 的内容块只有 text / reasoning / image / file / tool-*,模型模态只有 text / image
(见 ContentBlockMap 与 ModelModalityMap)——音频字节进不了模型上下文。
而官方语音链路是 speechToText.transcribe() → Transcript,也就是转写:
它把语气、停顿、重音、犹豫全部丢掉了。
本插件走旁路,把音频变成一份结构化文本证据再交给主模型:
音频 ──┬─ ① 本地声学层(零依赖·离线·不转写)
│ 语速 / 停顿结构 / 音高起伏 / 句尾走向 / 力度变化 / 唤醒度
│
└─ ② 听音模型层(可选·真的听过)
语义 + 情绪 + 重读 + 背景音 + 副语言线索
它不做什么(纪律)
- 不做转写。声学层
words恒为null,并在uncertainty里明说这一点。 - 不猜正负情绪。
impression.valence恒为无法判断(不猜)——声学无法可靠给出 valence。 - 不假装听见。检测不到人声就直说是静音/音乐/噪声;音频太短就直说特征不可靠。
- 印象标签标注为启发式·低置信,不给它披上"模型判断"的外衣。
安装(官方桌面端)
桌面端读 desktop profile,用内置 plugin_manager:
install_bundle target: link:<本目录绝对路径>
插件没有客户端半区(纯宿主),装完重启客户端即可;之后 listen_audio 会出现在工具表里。
配置
写在 profile 的插件配置里(include:ears):
mode: auto # auto | local | model
maxBytes: 12000000
toolName: listen_audio
address: 老大 # 怎么称呼用插件的人;也可用环境变量 EARS_ADDRESS 指定
# 想让它「真的听」时再加这一段;不加则只有声学层
model:
endpoint: https://your-endpoint/v1 # OpenAI 兼容
model: <一个支持音频输入的模型 id>
apiKeyEnv: EARS_API_KEY # 或直接写 apiKey(不推荐入库)
timeoutMs: 120000
jsonMode: true
听音模型层用的是 OpenAI 兼容的 chat/completions + input_audio 内容块。
任何支持音频输入的服务商都能用,只要它接受这个形状;本插件不绑定厂商。
用法
主模型(或你自己)调用:
listen_audio(path: "C:\\path\\to\\voice.wav", focus: "他是不是在敷衍我")
path:本地绝对路径或http(s)URL;容器按魔数判断,不信扩展名。mode: local时只跑声学层(离线,秒回)。- 同一份音频 + 同一 focus + 同一 mode 只计算一次(有缓存)。
输出长这样(一次真实运行,节选)
音频:wav · 8.64s · 276524B
说话方式:语速偏快、音高变化平、句尾平稳、句尾明显变弱、有 3 处停顿(含明显长停顿)
说话段 4 段 / 有效语音 6.48s(占比 0.75);停顿 3 处(最长 1100ms)
音高:均值 95.4Hz,起伏 σ=9.6Hz,首段走向 下沉,句尾平稳
力度:动态范围 13.4dB,句尾明显变弱
听感印象(启发式·低置信):唤醒度中等,候选 平稳陈述
不确定:声学层不做转写……;正面/负面情绪(valence)无法仅凭声学可靠判断,本工具不猜……
它不是一句「我觉得他有点不高兴」,而是让主模型能自己下结论的证据。
输出约定(说话的人怎么被回复)
听是手段,回话才是目的。插件把这条约定写进了工具描述,装了它的 Agent 默认照做:
- 先说听感,再说正文。 先用一两句大白话讲这段语音听着怎么样,再正常回答内容;
- 别念参数。 不报 Hz、σ、dB 这些数字,把它们翻成「语速快、结尾收得轻」这种人话;
- 别贴标签。 不要写「语气:」「分析如下」这类小标题——那会显得像在交作业;
- 可以活泼。 按自己的角色说话,该贫就贫,别端着;
- 称呼可自定义。 默认叫「老大」,在插件配置里写
address: 老板(或设环境变量EARS_ADDRESS)就能换成任何一种叫法——别把称呼写死; - 简短。 一句听感 + 一句正文,别铺陈。
一句话:先让人觉得「他真听出来了」,再办事。
支持格式
| 容器 | 本地声学层 | 说明 |
|---|---|---|
| wav | ✅ 内置解码 | PCM 8/16/24/32 位、float32/64、任意声道下混、EXTENSIBLE 外壳 |
| webm / ogg (opus) | ❌ | 需先转 wav,或配置听音模型层 |
| mp3 / m4a | ❌ | 同上 |
浏览器 MediaRecorder 默认出 webm/opus;要喂给本地层,先转成 wav
(例如 ffmpeg -i in.webm -ar 16000 -ac 1 out.wav)。
自检
node test/selfcheck.mjs
会合成一段参数已知的音频(3 段说话、2 处停顿、一段上扬、一段下沉、句尾变弱), 再让分析器把它读回来并逐项断言——不是看输出像不像,而是构造值能不能被还原。
目录
lib/index.js 插件入口:注册工具、缓存、编排两层
lib/wav.js 最小 WAV 解码器(无依赖)
lib/hearing.js 声学分析(VAD / F0 / 停顿 / 节奏 / 力度)
lib/model.js 听音模型层(OpenAI 兼容 input_audio)
test/selfcheck.mjs 已知结构音频的还原断言
已知边界
- 声学层的"语速"是音节率代理(浊音段内的能量峰计数),不是真正的音节识别;
- F0 用自相关,非浊音帧不估音高,
voicedFrames太少时相关指标会标为不可靠; - 听音模型层需要第三方端点 —— 音频会被发往那个端点,用之前先想清楚这一点;
- 本插件不做音频转码、不做录音 UI;前端"按住说话"的观感属于另一个插件的事。
更新记录
- 0.1.4 — README 开头补「它能做什么 / 别人做不到什么」;npm 关键词补
emotion、tone、语音、语气、声学。 - 0.1.3 — 称呼不再写死:新增配置项
address(环境变量EARS_ADDRESS兜底),默认「老大」;工具描述按配置取值,README 同步说明。 - 0.1.2 — 工具描述里写进「输出约定」:先说听感再说正文、不念参数、不贴标签、可以活泼、称呼用户「老大」、保持简短。README 增补同款说明。
- 0.1.1 — 修掉宿主注册失败:
OUTPUT_SCHEMA里的type: ['object','null']是宿主不接受的数组写法,改成单一类型;值层面改为永不返回 null(words空字符串、modelLayer给{ok:false})。 - 0.1.0 — 首个版本:本地声学层 + 可选听音模型层,
listen_audio工具。
Comments
Loading…
Similar plugins
by moazzamak
Offline local speech-to-text for the DeepSeek Harness composer: a microphone button that records, transcribes with faster-whisper on your own machine, and inserts the text into the chat draft.
★ 0
MIT
JavaScript
Oct 6, 2026
dsh plugin --profile web add dsh-voice-inputby Jesse-njx
Voice notes in, spoken answers out — dictate audio that becomes user messages (transcribe), have the agent read replies aloud (speak), and leave walk-away narration on long headless runs. Local-first:
★ 3
MIT
TypeScript
Aug 13, 2026
dsh plugin --profile web add @dsh-voice/bundleby QDchuan
Voice input for DeepSeek Harness: a microphone seat in the composer and a Web settings page that transcribes through the browser or any OpenAI-compatible /audio/transcriptions endpoint, with a fully o
★ 0
MIT
JavaScript
Sep 12, 2026
dsh plugin --profile web add dsh-voice-inputby kittcat-lab
Voice for the DeepSeek Harness: speak to the agent, hear it back, and see what it is doing from a floating window that stays on top of whatever you are running.
★ 0
↓ 386/wk
MIT
JavaScript
Sep 9, 2026
dsh plugin --profile web add dsh-kitt-voiceby 3274375092
Voice input plugin for DeepSeek Harness: mic → local/browser speech recognition → text submitted as a normal chat message. Input-only and preset-agnostic.
★ 8
↓ 158/wk
MIT
TypeScript
Oct 1, 2026
dsh plugin --profile web add @nn12138/dsh-voiceby yuezengwu
Private, local-first continuous learning for DeepSeek Harness: capture, review, and correct what Explain learns.
★ 12
MIT
TypeScript
Oct 20, 2026
dsh plugin --profile web add dsh-explain