dsh-voice-hotkey — 按键语音输入
按住一个键(默认 Option ⌥)开始录音,松开自动停止并转写,识别结果落进当前输入框草稿——不用再用鼠标点麦克风。
按住键可以在 设置 → 插件 → 按键语音输入 里改,改完立即生效并记进 profile,重启后仍是你的选择。
本插件不自己录音、不自己识别、不下载第二套模型:它只是把「按住 / 松开」翻译成官方语音输入插件
(@deepseek-ai/dsh-experimental-client-ui-voice-input)的两次点击,因此录音界面、识别模型、语言与
设备设置全部沿用官方那套。
English: hold a key (Option by default) to dictate into the DSH composer and release to transcribe. Recording, recognition and the model stay with the official voice-input plugin; this plugin only bridges keydown/keyup to that plugin's microphone and stop buttons. The hold key is configurable on the plugin page.
用起来是什么样
| 动作 | 底层发生的事 |
|---|---|
| 按住选定键 | 点官方麦克风按钮 → 官方录制栏出现、开始录音 |
| 松开 | 点录制栏里的「停止并识别」→ 转写并插入草稿 |
| 按住期间敲了别的键 | 点「取消」,这次按键照常生效(Option 不会变成第二个修饰键) |
| 上一轮识别失败/为空 | 再按住一次 = 点录制栏里的「重新录音」 |
| 窗口失焦 / 切页 | 取消本次录音(与官方插件自己的行为一致) |
自定义按住键
设置 → 插件 → 按键语音输入 → 配置区里点一个键:
| 可选键 | 说明 |
|---|---|
| Option ⌥ | 默认,左 Option |
| 右 Option ⌥ | 左右手更顺时用 |
| 右 Shift ⇧ | 小指按住,不输入字符 |
| 右 Ctrl ⌃ | 同上 |
| F2 | 功能键;macOS 默认需按 Fn+F2 |
候选键定义在 client.js 的 KEY_OPTIONS 里,加一行就多一个选项(Host 侧 Config 的
holdKey 是普通字符串,客户端会校验它是否在候选表里)。
它是怎么实现的
两个半侧加起来很薄,没有后台常驻任务:
src/index.js(Host):只声明Config = z.object({ holdKey: z.string().default('AltLeft').volatile() })。.volatile()让 DSH 的设置表单能在不重载插件的情况下改它,并写回 profile patch——所以选择能跨重启保留 (GUI 每次启动的端口不同,localStorage靠不住)。client.js(浏览器):- 文档级
keydown/keyup(capture 阶段)驱动按键状态机; - 用
document.querySelector找到官方插件的麦克风 / 停止 / 重试按钮并.click(), 官方 DOM 只用稳定的类名后缀与data-voice-activity属性定位,失效时退化为aria-label匹配; - 通过客户端
configForms服务读写holdKey,并在插件页注册配置卡片; - 不联网、不读麦克风、不写文件,唯一的状态是「这一次按住到哪一步了」。
- 文档级
依赖
- DSH Desktop 0.2.1 及以上(用到了
plugins.bundle.configslot 与configForms服务); - 官方语音输入已就位:设置 → 插件里
@deepseek-ai/dsh-experimental-voice-input-bundle已启用, 本地识别模型已准备好(点一次官方麦克风按钮,按提示下载一次即可); - Host 侧依赖
@deepseek-ai/schemastery(见package.json)。
安装
# 从本地目录安装(开发时)
dsh plugin --profile desktop add link:/path/to/dsh-voice-hotkey
# 或从 git 安装
dsh plugin --profile desktop add git+https://github.com/wengyingjian/dsh-voice-hotkey.git
装好后重启 DSH(没有启用 HMR 的 profile 需要重启才会挂上新的插件行)。
手工等价做法:把包目录软链到 ~/.dsh/profiles/<profile>/node_modules/dsh-voice-hotkey,并在 profile 的
package.json 里登记依赖与 dsh.profile.bundles(本包自带 cordis.patch.yml,组合时会 insert 插件行
voice-hotkey)。
边界与已知限制
- 不用先把光标点进输入框:只要当前视图有输入框,按住选定键会自己把焦点交给输入框再开始 (在看记录、点了侧栏按钮时也能直接按住说话)。只有焦点停在别的输入框里(设置页搜索框等)才让出按键。
- 设置页等没有输入框的视图不触发;弹窗、菜单打开时让出按键。
- 键盘事件来自页面本身:DSH 窗口在后台(切到别的 app)时收不到按键。系统级「全局按住说话」需要
宿主半侧调用 Electron
globalShortcut,本插件只做网页层,不涉及。 - 按住时间太短(录音不足)会由官方插件提示「未识别到语音」;此时直接再按住一次即可重录。
- 首次使用会弹系统麦克风授权;授权对话框可能让窗口失焦而取消这一次,授权后第二次按住即正常。
- 官方插件的类名带 CSS Modules 哈希前缀,本插件按类名后缀(
triggerAnchor/_trigger)与data-voice-activity属性定位;若 DSH 升级改了结构,按住键会「没反应」而不是乱点,届时改client.js里的TRIGGER_SELECTORS即可,兜底的aria-label匹配(开始录音/Start recording)也会继续工作。 - 不用官方快捷键服务(
ctx.shortcuts):它只派发keydown、没有keyup,且要求组合必须带修饰键, 表达不了「按住一个键说话」。 - 设置表单写入的是 profile patch 里
voice-hotkey这一行的config.holdKey;如果这一行被更高层 (如命令行--patch)固定成别的值,DSH 会拒绝这次写入,卡片会提示保存失败。
测试
node --test test/hotkey.test.mjs
测试用 test/fake-dom.mjs 里的最小 DOM 桩验证按键状态机、安全边界与设置同步;真实选择器与设置写入
仍需在 DSH 窗口里实测。
文件
| 文件 | 作用 |
|---|---|
src/index.js |
Host 半侧:声明 holdKey 的 Config(设置表单的唯一来源),无其他行为 |
client.js |
浏览器半侧:键盘状态机 + 驱动官方语音输入插件的按钮 + 插件页配置卡片 |
cordis.patch.yml |
bundle patch:把插件行插进 profile 根层 |
locale/{zh,en}.json |
插件在插件列表里的标题与描述 |
test/ |
最小 DOM 桩与用例 |
许可
MIT
No comments yet. Be the first to write one.