Bundle
dsh-voice-f9
全局「按住说话」语音输入:按住 F9 说话、松手出字,任意 Windows 程序可用;本地 SenseVoice 识别,不联网、不占显卡。Hold-to-talk voice input for any Windows app, local SenseVoice via sherpa-onnx.
- Source
- uniwell9797
- License
- MIT
- Updated
- Updated 9 days ago
Readme
# dsh-voice-f9
全局「按住说话」语音输入,装进 DeepSeek Harness。
按住 **F9** 说话 → 松手 → 文字直接落进光标处。**任何 Windows 程序都能用** ——
微信、Word、浏览器、IDE、通达信,不限于 DSH 自己的输入框。
识别全程在本机跑(sherpa-onnx + SenseVoice int8),不联网、不占显卡、
音频不出本机;实测进程 **TCP 0 条 / UDP 0 个**。
## 它做了什么
这个插件本身不是识别引擎,而是一层**生命周期管理**:DSH 起来时把那个本地语音输入
程序拉起来,DSH 退出时收掉它,并把配置(热键、浮标、模型路径)托管好。
| 你关心的事 | 插件行为 |
| --- | --- |
| 装完就能用 | 首次激活自动把程序文件铺到 `<DSH_HOME>/voice-f9/` |
| 模型从哪来 | **不重新下载**,默认复用 DSH 自带本地语音的那一份(见下) |
| 热键 | 默认 `F9`;这台机器上 F9 是静音媒体键也能用(见「F9 是静音键」) |
| 重复启动 | 程序自带单实例保护,插件和开机自启同时拉起也只会活一个 |
| 出问题看哪 | `<DSH_HOME>/voice-f9.log`(插件)+ `<DSH_HOME>/voice-f9/语音输入日志.txt`(程序) |
## 依赖
1. **Windows**(这个程序用了 Win32 取光标位置、`winsound`、`Ctrl+V`;其他平台会跳过启动)。
2. **Python 3.10+**,并装好这几个库:
```powershell
python -m pip install sherpa-onnx sounddevice numpy pyperclip keyboard uiautomation
```
插件默认找 `pythonw.exe`;找不到就在配置里填 `pythonPath`。
3. **SenseVoice int8 模型**(`model.int8.onnx` 239MB + `tokens.txt`)。
默认路径是 `<DSH_HOME>/speech-to-text/sensevoice` —— 也就是 **DSH 自带本地语音
输入用的同一份模型**。两者是同一個文件(哈希一致),所以装两次只占一份磁盘。
如果你还没让 DSH 下过模型,也可以把已有的模型放到别处,再用配置里的 `modelDir`
指过去。**不建议重新下载**:`huggingface.co` 会重定向到 `us.aws.cdn.hf.co`,
实测国内直连约 0.5 MB/s,239MB 要七八分钟,走代理更慢。
## 安装
```sh
dsh plugin --profile <你的 profile> add dsh-voice-f9
```
装完重启 DSH(或让它热加载)。之后进 **设置 → 插件 → 插件配置** 调参数。
## 配置
**本插件不声明 `Config` schema**,所以没有自动生成的设置表单 —— 这是刻意的取舍,
原因见下面「为什么没有设置表单」。配置写在 profile 的 `cordis.patch.yml` 里:
```yaml
- id: dsh-voice-f9
name: dsh-voice-f9
config:
hotkey: f9 # 可写空格分隔的多个键;对讲机模式不支持组合键
indicator: true # 屏幕上跟着光标跑的小胶囊
pythonPath: 'C:\Python314\pythonw.exe'
sherpaThreads: 4
graceMs: 3000
```
| 字段 | 默认 | 说明 |
| --- | --- | --- |
| `enabled` | `true` | 关掉就不启动,但文件还在 |
| `pythonPath` | 自动探测 | `pythonw.exe` 的绝对路径 |
| `dataRoot` | `<DSH_HOME>/voice-f9` | 程序文件放哪 |
| `modelDir` | `<DSH_HOME>/speech-to-text/sensevoice` | 模型放哪 |
| `hotkey` | `f9` | 可写空格分隔的多个键(对讲机模式只支持单键,不支持组合键) |
| `indicator` | `true` | 屏幕上跟着光标跑的小胶囊 |
| `sherpaThreads` | `4` | 推理线程数 |
| `graceMs` | `3000` | 要求子进程退出后的宽限期;`spawn` 强制要求这个字段 |
字段写错、类型不对、甚至整个 `config` 是 `null` 或字符串,都会被插件内部的
`normalizeConfig()` 兜回默认值,**不会崩、也不会拒绝加载**。
## 为什么没有设置表单
因为它需要 `import z from '@deepseek-ai/schemastery'`,而这个导入**可能解析失败**:
插件常以软链(`link:`)方式安装,Node 会按**真实路径**向上找 `node_modules`;
一旦某个组合里没有把 `@deepseek-ai/schemastery` 铺到可达位置,
整个插件就是 `failed to import` —— **所有功能全废,连"没模型"这类提示都发不出来**。
这个坑是实测踩到的,不是假想:
```
dsh: warning: 1 entry did not activate
dsh-voice-f9 (dsh-voice-f9): failed to import
```
所以本插件**零外部导入**,配置校验全部手写。代价只是没有表单,换来的是"一定能加载"。
## 用法
| 操作 | 效果 |
| --- | --- |
| 按住 `F9` 说话 | 开始录音(浮标变红) |
| 松开 | 识别(0.1~0.3 秒)→ 文字进光标处 |
| 录音时按 `Esc` | 丢弃这段 |
| 右键点浮标两次 | 退出程序 |
## 已知行为
**F9 是静音键也能用。** 有些笔记本(如 ASUS Zenbook 14)的 F9 默认是静音媒体键,
发的是 `VK_VOLUME_MUTE` 而不是 `VK_F9`。随包的程序把 `volume mute` 也绑成候选键,
且 `suppress=True` 会把这个键吞掉,所以按住 F9 是说话、**不会再静音**。
**浮标会跟着光标跑。** 走 UIA `TextPattern.GetSelection()` 拿真实光标位置,跨应用、
跨屏都跟得上(Chromium/Electron 不提供 `hwndCaret`,所以不能靠 Win32 那条路)。
想让它钉住不动,把 `indicator_pos` 改成 `top-right` 之类即可。
**和开机自启共存。** 如果你之前用安装包装过一次,注册表
`HKCU\...\CurrentVersion\Run` 里可能还有一个 `VoiceInputF9`。两边同时拉起也安全 ——
程序自带命名互斥体,第二份会自己退出并在日志里写明。想只让插件管,把那条自启删掉即可。
## 出问题了看哪
1. `<DSH_HOME>/voice-f9.log` —— 插件走到哪一步、失败原因。**先看它。**
2. `<DSH_HOME>/voice-f9/语音输入日志.txt` —— 程序自身:热键有没有绑上、模型加载用了多久。
3. 缺模型、缺 Python 这类问题**不会**把宿主拖垮:插件会记一条 warn 然后跳过启动。
## 许可
MIT。随包的程序与 SenseVoice 模型来自各自上游,请遵守其许可。
Install
dsh plugin --profile web add github:uniwell9797/dsh-voice-f9
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-voice-f9 from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.