dsh-dictation-hotkey
Verifieddsh-dictation-hotkey · v0.3.0 · MIT · Web UI
Press-to-talk dictation: a key combination records in the DSH Web page, DSH's own speech engine transcribes, and the text lands in the composer.
Install
dsh plugin add dsh-dictation-hotkey Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
dsh-dictation-hotkey(中文说明)
给 DSH Web 输入框加一个「按住说话」入口:按住组合键说话,松开后由 DSH 自带的语音引擎识别,文字直接落进输入框。
本插件不引入第二个识别器 —— 它调用 DSH 语音输入 Bundle 已经在用的那个语音 Remote(本地 SenseVoice,CPU 推理),并通过官方 composer 动作写入文字。
按住 Ctrl+Shift+Space ──▶ 说话 ──▶ 松开
│
├─ 页面内麦克风采集(getUserMedia + AudioWorklet,静音输出不外放)
├─ 编码为 Remote 要求的规范 16 kHz 单声道 PCM16 WAV
├─ ctx.remote.speech.transcribe() ← 官方语音 Remote(SenseVoice)
└─ inputActions.insertText() / submit() ← 官方 composer
功能
- 按住说话:
按住(按住期间录音)或开关(按一下开始、再按一下结束)两种触发方式。 - 填入或发送:识别结果只填入输入框供你检查,或立刻发送。
- 复用 DSH 引擎:与官方麦克风按钮同一个本地 SenseVoice Provider,不额外起进程、不下载模型、不走云端 API。
- 原生插入:通过
inputActions.insertText写进当前草稿,光标位置、引用与附件都不受影响。 - 按浏览器配置:热键、触发方式、是否发送、提示音、诊断日志都在输入框下方胶囊的弹窗里改(存
localStorage)。 - 新会话页同样可用:没有会话时不存在可插入的草稿,识别结果会以正常编辑的方式粘贴进当前聚焦的输入框;进入会话后胶囊回来。
- 可诊断:可选逐次按键日志,含音频电平、音频长度、识别耗时,能明确区分「没拾到声音」与「引擎漏识」。
环境要求
- DSH
0.2.0-rc.2或兼容版本,web profile。 - 已启用官方语音输入 Bundle(插件管理页 → 语音输入),它提供识别引擎;未启用时胶囊会提示识别未挂载。
安装
# 从本地目录
dsh plugin --profile web add /path/to/dsh-dictation-hotkey
# 或直接从 git 安装(不用 clone、不用构建:产物已提交)
dsh plugin --profile web add github:AndyYang12345/dsh-dictation-hotkey
然后刷新 Web 页面。构建产物 client/dist/client.js 已随仓库提交,直接 checkout 也能用,无需构建。
以后更新:再执行一次
dsh plugin --profile web add github:AndyYang12345/dsh-dictation-hotkey,然后重启 dsh web。
profile 会保存已安装包的一份副本,所以只往 GitHub 推送并不会自动更新已安装的 profile。
使用
输入框下方出现 🎙 听写 胶囊:
| 操作 | 结果 |
|---|---|
按住 Ctrl+Shift+Space 说话,松开 |
识别结果写入输入框 |
| 点击胶囊 | 设置:热键(按下即录制)、只填入 ↔ 自动发送、按住 ↔ 开关、提示音、诊断日志 |
松键时抬起组合键中的任意一个键都会结束录音,不需要三个键同时松开。
在新会话页(还没有会话时)看不到胶囊 —— 输入框停靠槽只在会话内存在 —— 但快捷键依然可用: 控制器通过一个根作用域的席位保持待命,识别结果粘贴进当前聚焦的输入框;该页面不自动发送,发送仍由你回车决定。
诊断
在弹窗里勾选诊断日志后,每次按键都会记录一条结构化数据(同时打到 DevTools 控制台,并在 localStorage 的 dsh-dictation-hotkey.log 保留最近 20 条,弹窗内可复制/清空):
event |
含义 |
|---|---|
start |
麦克风就绪 —— micStartMs、触发键 heldCodes |
stop |
松键 —— heldMs、tailMs |
ok |
识别成功 —— audioSeconds、inferenceMs、chars、peakDb |
empty-transcript |
引擎返回空 —— 含 peakDb;quiet: true 表示那一次几乎没有有效声音 |
skip |
被门槛拦下:shorter than minRecordMs、empty audio、speech remote absent |
transcribe-failed / mic-failed / insert-conflict / finish-threw |
对应故障 |
peakDb > -45 却识别为空 → 问题在识别(可调 language);peakDb < -45 → 那一次本来就没拾到有效声音。
开发
npm run build # 构建 client/dist/client.js(esbuild)
npm run verify # 契约自检:产物只触碰 inject 中声明的服务
npm test # 行为测试:假麦克风 + 假识别引擎
verify.mjs 的由来:Cordis 里读未声明的服务会抛
cannot get property "slots" without inject,而 Web 外壳只显示一行
web boot: 1 entry did not activate —— 本插件踩过一次,现在把它变成构建期检查。
test-release.mjs 覆盖松键顺序、连点、过短按住、空结果、自动发送。
限制
- 只在 DSH 页面获得焦点时响应按键;其他窗口在前台时按键不会到达插件,系统级支持需要额外的操作系统层守护进程(未实现)。
- 麦克风授权按 DSH 站点授予;首次使用可能需要先点一次官方麦克风按钮。
- 录音受
maxRecordSeconds与 Remote 自身的音频上限约束。
许可
MIT © 2026 AndyYang12345