Skip to content

Commit a82e8d0

Browse files
committed
feat: harden side-button workflow and Wayland output routing
Improve reliability for side-button mapping, recording lifecycle, and Hyprland text submission so daily voice input use is stable on Linux.
1 parent 96721db commit a82e8d0

11 files changed

Lines changed: 1166 additions & 118 deletions

File tree

README.md

Lines changed: 163 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,63 @@
11
# VibeMouse
22

3-
按鼠标前侧键开始录音,再按一次结束录音并自动转文字。识别结果优先输入到当前焦点输入框;如果没有可编辑输入框,则自动写入剪切板。鼠标后侧键用于发送 Enter。
3+
**Mouse-side-button voice input for VibeCoding on Linux.**
44

5-
语音识别引擎使用 SenseVoice,支持两种后端:
5+
中文文档:[`README.zh-CN.md`](./README.zh-CN.md)
66

7-
- `funasr`(PyTorch)
8-
- `funasr_onnx`(ONNXRuntime,Intel NPU 机器建议优先)
7+
VibeMouse turns your mouse side buttons into a fast coding workflow:
98

10-
默认 `VIBEMOUSE_BACKEND=auto`,会自动选择更可用的后端。
9+
- 🎙️ Press side button to start/stop recording
10+
- ✍️ Auto speech-to-text with SenseVoice
11+
- ⌨️ Type into focused input, or fallback to clipboard
12+
- ↩️ Another side button sends Enter
1113

12-
## 功能
14+
If you spend hours in ChatGPT / Claude / IDEs and want to keep one hand on the mouse, this is for you.
1315

14-
- 前侧键(默认 `x1`):
15-
- 第一次按下:开始录音
16-
- 第二次按下:结束录音,触发 SenseVoice 转写
17-
- 后侧键(默认 `x2`):发送回车
18-
- 转写输出策略:
19-
- 当前有可编辑输入焦点:直接键入
20-
- 否则:复制到剪切板
21-
- 后端/设备策略:
22-
- 默认 `VIBEMOUSE_BACKEND=auto`
23-
- 默认 `VIBEMOUSE_DEVICE=cpu`(当前最稳)
24-
- 在 Intel NPU 场景下,`auto` 会优先尝试 `funasr_onnx`
25-
- 若后端或设备失败且 `VIBEMOUSE_FALLBACK_CPU=true`,自动降级 CPU
16+
---
2617

27-
## 系统要求(Linux)
18+
## Why VibeMouse?
2819

20+
When VibeCoding, your flow is usually:
21+
22+
1. Think
23+
2. Speak prompt
24+
3. Submit
25+
26+
VibeMouse binds that to mouse side buttons so you can do it with minimal context switching.
27+
28+
---
29+
30+
## Features
31+
32+
- Global mouse side-button listening
33+
- Start/stop recording with one side button
34+
- Speech recognition using SenseVoice
35+
- Smart output routing:
36+
- If focused element is editable → type text directly
37+
- Otherwise → copy text to clipboard (or auto paste when enabled)
38+
- Dedicated side button for Enter
39+
- CPU-first stable default (works reliably)
40+
- Optional backend switching (`funasr` / `funasr_onnx`)
41+
42+
---
43+
44+
## Current Platform
45+
46+
- Linux
2947
- Python 3.10+
30-
- 音频录制支持(PortAudio / ALSA / PulseAudio)
31-
- 全局输入监听权限(`/dev/input/event*`,推荐将用户加入 `input` 组)
32-
- AT-SPI 可访问性(用于判断当前焦点是否为可编辑输入框)
33-
- 本地 NPU 运行环境(推荐 Intel NPU + OpenVINO 可用)
3448

35-
建议先安装系统依赖(Debian/Ubuntu 示例):
49+
---
50+
51+
## Quick Start
52+
53+
### 1) Install system packages (Ubuntu/Debian)
3654

3755
```bash
3856
sudo apt update
3957
sudo apt install -y python3-gi gir1.2-atspi-2.0 portaudio19-dev libsndfile1
4058
```
4159

42-
## 安装
60+
### 2) Install VibeMouse
4361

4462
```bash
4563
python3 -m venv .venv
@@ -48,88 +66,158 @@ pip install -U pip
4866
pip install -e .
4967
```
5068

51-
## 运行
69+
### 3) Run (recommended stable mode)
5270

5371
```bash
72+
export VIBEMOUSE_BACKEND=auto
73+
export VIBEMOUSE_DEVICE=cpu
5474
vibemouse
5575
```
5676

57-
或:
77+
---
78+
79+
## Default Button Mapping
80+
81+
- `x1` → voice button (start/stop recording)
82+
- `x2` → Enter
83+
84+
If your mouse is reversed:
5885

5986
```bash
60-
python -m vibemouse.main
87+
export VIBEMOUSE_FRONT_BUTTON=x2
88+
export VIBEMOUSE_REAR_BUTTON=x1
89+
vibemouse
6190
```
6291

63-
## 环境变量配置
92+
---
93+
94+
## How It Works
95+
96+
1. Press voice side button once → recording starts
97+
2. Press again → recording stops, transcription runs
98+
3. If current focus is editable input → text is typed
99+
4. Otherwise text is copied to clipboard
100+
5. Press Enter side button to submit
64101

65-
| 变量 | 默认值 | 说明 |
102+
---
103+
104+
## Configuration
105+
106+
Environment variables:
107+
108+
| Variable | Default | Description |
66109
|---|---|---|
67-
| `VIBEMOUSE_BACKEND` | `auto` | 转写后端:`auto` / `funasr` / `funasr_onnx` |
68-
| `VIBEMOUSE_MODEL` | `iic/SenseVoiceSmall` | 模型名/路径(`funasr_onnx` 推荐 `iic/SenseVoiceSmall-onnx`|
69-
| `VIBEMOUSE_DEVICE` | `cpu` | 设备偏好(默认 CPU 稳定模式;可手工设为 `npu:0` / `cuda:0`|
70-
| `VIBEMOUSE_FALLBACK_CPU` | `true` | 设备失败时是否自动退回 CPU |
71-
| `VIBEMOUSE_LANGUAGE` | `auto` | 语言(`auto`/`zh`/`en`/`yue`/`ja`/`ko`|
72-
| `VIBEMOUSE_USE_ITN` | `true` | 是否启用 ITN |
73-
| `VIBEMOUSE_ENABLE_VAD` | `true` | 是否启用 `fsmn-vad` |
74-
| `VIBEMOUSE_VAD_MAX_SEGMENT_MS` | `30000` | VAD 单段最大毫秒数 |
75-
| `VIBEMOUSE_MERGE_VAD` | `true` | 是否合并 VAD 碎片 |
76-
| `VIBEMOUSE_MERGE_LENGTH_S` | `15` | 合并长度(秒) |
77-
| `VIBEMOUSE_SAMPLE_RATE` | `16000` | 录音采样率 |
78-
| `VIBEMOUSE_CHANNELS` | `1` | 录音声道 |
79-
| `VIBEMOUSE_DTYPE` | `float32` | 录音数据类型 |
80-
| `VIBEMOUSE_FRONT_BUTTON` | `x1` | 前侧键(`x1``x2`|
81-
| `VIBEMOUSE_REAR_BUTTON` | `x2` | 后侧键(`x1``x2`|
82-
| `VIBEMOUSE_TEMP_DIR` | 系统临时目录下 `vibemouse` | 临时录音目录 |
83-
84-
示例:
110+
| `VIBEMOUSE_BACKEND` | `auto` | `auto` / `funasr` / `funasr_onnx` |
111+
| `VIBEMOUSE_MODEL` | `iic/SenseVoiceSmall` | Model id/path |
112+
| `VIBEMOUSE_DEVICE` | `cpu` | Preferred device (`cpu`, `cuda:0`, `npu:0`) |
113+
| `VIBEMOUSE_FALLBACK_CPU` | `true` | Fallback to CPU if preferred device fails |
114+
| `VIBEMOUSE_BUTTON_DEBOUNCE_MS` | `150` | Ignore repeated side-button presses within this window |
115+
| `VIBEMOUSE_ENTER_MODE` | `enter` | Rear button enter mode: `enter`, `ctrl_enter`, `shift_enter`, `none` |
116+
| `VIBEMOUSE_AUTO_PASTE` | `false` | Auto paste with Ctrl+V after copying fallback text |
117+
| `VIBEMOUSE_TRUST_REMOTE_CODE` | `false` | Set `true` only for trusted models that require remote code |
118+
| `VIBEMOUSE_LANGUAGE` | `auto` | `auto`, `zh`, `en`, `yue`, `ja`, `ko` |
119+
| `VIBEMOUSE_USE_ITN` | `true` | Enable text normalization |
120+
| `VIBEMOUSE_ENABLE_VAD` | `true` | Enable VAD |
121+
| `VIBEMOUSE_VAD_MAX_SEGMENT_MS` | `30000` | Max VAD segment length |
122+
| `VIBEMOUSE_MERGE_VAD` | `true` | Merge VAD segments |
123+
| `VIBEMOUSE_MERGE_LENGTH_S` | `15` | Merge threshold in seconds |
124+
| `VIBEMOUSE_SAMPLE_RATE` | `16000` | Recording sample rate |
125+
| `VIBEMOUSE_CHANNELS` | `1` | Recording channels |
126+
| `VIBEMOUSE_DTYPE` | `float32` | Recording dtype |
127+
| `VIBEMOUSE_FRONT_BUTTON` | `x1` | Voice button (`x1` or `x2`) |
128+
| `VIBEMOUSE_REAR_BUTTON` | `x2` | Enter button (`x1` or `x2`) |
129+
| `VIBEMOUSE_TEMP_DIR` | system temp | Temp audio path |
130+
131+
---
132+
133+
## Troubleshooting
134+
135+
### Side button not detected
136+
137+
Likely Linux input permission issue. Add your user to `input` group and relogin:
85138

86139
```bash
87-
export VIBEMOUSE_DEVICE=npu:0
88-
export VIBEMOUSE_LANGUAGE=auto
89-
vibemouse
140+
sudo usermod -aG input $USER
90141
```
91142

92-
Intel NPU 推荐配置(自动优先 ONNX 后端):
143+
### Text is not typed into app
144+
145+
Some apps do not expose editable accessibility metadata. In that case VibeMouse falls back to clipboard by design.
146+
147+
### Rear button Enter feels unreliable
148+
149+
Try a different submit combo and reduce accidental repeated clicks:
93150

94151
```bash
95-
export VIBEMOUSE_BACKEND=auto
96-
export VIBEMOUSE_MODEL=iic/SenseVoiceSmall-onnx
97-
export VIBEMOUSE_DEVICE=npu:0
98-
vibemouse
152+
export VIBEMOUSE_ENTER_MODE=ctrl_enter
153+
export VIBEMOUSE_BUTTON_DEBOUNCE_MS=220
154+
systemctl --user restart vibemouse.service
99155
```
100156

101-
稳定推荐(先用这个):
157+
For Hyprland, you can move Enter to a compositor-level bind and disable VibeMouse rear-button Enter:
158+
159+
```ini
160+
# ~/.config/hypr/UserConfigs/UserKeybinds.conf
161+
bind = , mouse:276, sendshortcut, , Return, activewindow
162+
```
102163

103164
```bash
104-
export VIBEMOUSE_BACKEND=auto
105-
export VIBEMOUSE_DEVICE=cpu
106-
vibemouse
165+
export VIBEMOUSE_ENTER_MODE=none
166+
systemctl --user restart vibemouse.service
167+
hyprctl reload config-only
107168
```
108169

109-
## 权限说明
170+
### Recording works but recognition empty
171+
172+
Check microphone gain/input source first. Also verify your sample is not silent.
173+
174+
---
110175

111-
如果程序无法监听侧键,通常是输入设备权限问题。可将当前用户加入 `input` 组并重新登录:
176+
## About NPU/OpenVINO
177+
178+
NPU support depends on model graph compatibility with the NPU compiler.
179+
180+
In this project, **CPU default is intentional** for stability. If NPU compile fails, app behavior remains usable via CPU fallback.
181+
182+
---
183+
184+
## Run as background process (optional)
185+
186+
You can run with tmux/screen/systemd for always-on workflow.
187+
188+
Example (tmux):
112189

113190
```bash
114-
sudo usermod -aG input $USER
191+
tmux new -d -s vibemouse "source .venv/bin/activate && vibemouse"
192+
tmux attach -t vibemouse
115193
```
116194

117-
## SenseVoice / NPU 说明
195+
---
196+
197+
## Project Layout
118198

119-
项目内部支持两条推理链路:
199+
```text
200+
vibemouse/
201+
app.py # app orchestration
202+
audio.py # recording
203+
mouse_listener.py# side-button listener
204+
transcriber.py # ASR backends
205+
output.py # type/clipboard/enter output
206+
config.py # env config
207+
main.py # CLI entry
208+
```
120209

121-
1) `funasr`
210+
---
122211

123-
- `AutoModel(model="iic/SenseVoiceSmall", trust_remote_code=True, device="...")`
124-
- `model.generate(...)`
125-
- `rich_transcription_postprocess(...)`
212+
## Development
126213

127-
2) `funasr_onnx`
214+
```bash
215+
python -m compileall vibemouse
216+
python -m pip check
217+
```
128218

129-
- `SenseVoiceSmall(model_dir="iic/SenseVoiceSmall-onnx", quantize=True, ...)`
130-
- `model(audio_path, language=..., textnorm=...)`
131-
- `rich_transcription_postprocess(...)`
219+
---
132220

133-
> 注意:当前 `funasr_onnx` 官方 Python 实现主要支持 CPU / CUDA provider;Intel NPU 设备虽可被 OpenVINO 识别,但直接对 SenseVoice ONNX 编译到 NPU 可能因动态形状限制失败。此时会自动回退 CPU。若要强制 NPU,需要额外的静态图改造/编译流程。
221+
## License
134222

135-
如果你的 NPU 栈需要额外 runtime,请先按本机驱动文档安装好再运行。
223+
This project uses upstream dependencies (SenseVoice/FunASR/OpenVINO, etc.) under their respective licenses.

0 commit comments

Comments
 (0)