前言¶
在 DeepSeek Harness(DSH)里做对话或回答 Agent 提问时,语音输入往往比长段打字更顺手。DSH 自带实验性语音输入插件会把麦克风挂在固定 UI 槽位上;当 ask_user_question 弹出提问卡片时,输入栏槽位会被提问 UI 顶替,麦克风按钮消失,主观作答框就无法继续语音输入。社区插件 dsh-voice-hotkey(维护者 caly250,分类:模型推理)用全局快捷键代替槽位绑定:按住 F9 说话,松开后走本机 SenseVoice 识别,把文字写进当前获得焦点的输入框——对话 composer、提问卡片里的 textarea,或页面上任意 input / textarea / contenteditable。
这是什么¶
dsh-voice-hotkey 是 DSH 的 Host + Client 双半侧插件:浏览器侧在 window 捕获阶段监听快捷键并录音;Host 侧暴露 HTTP 接口,把 WAV 交给 DSH 内置语音 Bundle 的识别器。它不占用 conversation.input.activity 等槽位,因此在提问卡片接管 composer 时仍可对着作答框语音输入。
- 目录页:skillhub.cn/plugins/caly250/dsh-voice-hotkey
- 源码与说明:github.com/caly250/dsh-voice-hotkey
- 许可证:MIT(README);package.json 版本 1.0.0,Node >=20
社区插件目录为独立站点,与 DeepSeek / 幻方无官方从属关系;安装前请自行审阅源码与许可证。插件随当前 DSH 进程权限运行。
与内置语音输入的差异¶
内置 @deepseek-ai/dsh-experimental-client-ui-voice-input 依赖 UI 槽位。本插件不占用任何槽位,在哪个输入框获得焦点、就在哪里插入识别结果。内置能力仍可作为对比参考;需要「提问卡片里也能说」时,更适合用快捷键方案。
前置条件¶
识别依赖 DSH 实验性语音 Bundle,而非插件自带模型:
- Profile 的
dsh.profile.bundles中需包含@deepseek-ai/dsh-experimental-voice-input-bundle。 - 模型 SenseVoiceSmall INT8(约 230 MB)需已在
$DSH_HOME/speech-to-text(首次启用语音 Bundle 时通常会自动下载)。
未配置语音 Bundle 时插件仍可加载,但 GET /api/dsh-voice-hotkey/status 会报服务不可用,POST /api/dsh-voice-hotkey/transcribe 返回 503。
核心功能¶
- 按住说话:默认按住
F9录音,松开触发识别(可改为 toggle 模式)。 - 本地识别:通过 Host 路由把 PCM WAV 交给
ctx.get('speechToText')(SenseVoice)。 - 焦点插入:按下快捷键时的
document.activeElement优先;另有提问框、composer 等回退链。 - 状态浮标:录音(红点 + 音量)、识别中(黄点)、成功/失败提示;平时
pointer-events: none,避免挡住底部输入栏。 - 安全边界:两条 API 仅接受回环地址,并校验
Host头;因 exact 路由会绕过浏览器 cookie 鉴权,必须自行做 localhost 校验。 - 刻意不做:自动发送、常开麦、唤醒词、流式字幕;页面失焦时快捷键不生效。
安装与启用¶
README 给出的安装方式如下(请将 <your-user> 换成实际 GitHub 用户名或组织):
# 从 GitHub 安装
dsh plugin --profile desktop add github:<your-user>/dsh-voice-hotkey
# 或从本地目录
dsh plugin --profile desktop add link:/path/to/dsh-voice-hotkey
启用后:
- Host 半侧随 profile 的
patchReload: live即时生效。 - 浏览器侧需刷新页面一次才会加载 Client 脚本。
配置¶
DSH loader 对客户端插件只传 { name: id },读不到 profile 里的 config,因此选项写在 localStorage['dsh-voice-hotkey']:
localStorage.setItem('dsh-voice-hotkey', JSON.stringify({
key: 'F9', // KeyboardEvent.code
modifiers: [], // 例如 ['ctrl','shift']
holdToTalk: true, // false = 按一下开始、再按一下结束
maxSeconds: 120,
showIndicator: true
}))
缺省即上表。若 F9 被其他软件全局占用,把 key 改为 F8、KeyG 等(使用 event.code 命名)。
典型用法¶
- 确认语音 Bundle 与模型已就绪(必要时先看
/status)。 - 在 DSH 桌面 profile 安装插件并刷新浏览器。
- 光标放入要输入的位置(对话框、提问作答框或普通表单)。
- 按住 F9 说话,松开后等待识别;成功时文字插入当前焦点控件,顶部浮标约 1.5 秒后消失。
- 录音过程中若窗口失焦、页面隐藏或按 Escape,会取消录音,避免麦克风常开。
Host 侧诊断可用:
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /api/dsh-voice-hotkey/status |
识别器状态 |
| POST | /api/dsh-voice-hotkey/transcribe |
body {audioBase64, providerId?, language?} → {ok, text} |
/transcribe 要求规范 44 字节头的 16 kHz 单声道 PCM16 WAV,body 上限 6 MB / 120 秒;浏览器侧会用 OfflineAudioContext 重采样并编码,以兼容识别器校验。
适用场景与注意¶
适合:希望在 DSH 任意输入场景(含提问卡片)用同一套快捷键做本地语音输入、且已启用实验性语音 Bundle 的开发者。
注意:
- 需浏览器麦克风权限;被拒时会给出专门提示。
- 输入法组合态(
isComposing或keyCode === 229)不会抢键。 - 空结果分两类:音频短于 0.5 秒与「有音频但未识别到语音」,提示不同。
- 出问题时查看
localStorage['dsh-voice-hotkey-probe'],常见 phase 从listeners-installed到inserted;停在failed/getusermedia-failed时看extra字段原因。
JSON.parse(localStorage.getItem('dsh-voice-hotkey-probe'))
Lexical composer 等编辑器对 execCommand('insertText') 异步提交 DOM;插件用「内容是否变化 + 宏任务宽限」避免同一句话插两遍,属于集成细节,一般只需知道「成功时只应出现一次文本」即可。
结尾¶
dsh-voice-hotkey 把「按住说话、松开识别、插入焦点」做成与 UI 槽位无关的快捷键流程,补上提问卡片等场景下内置麦克风不可用的问题。安装命令与配置以 README 为准;进一步实现细节(WAV 形态、回环鉴权、插入优先级)见 GitHub 文档。