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
3856sudo apt update
3957sudo apt install -y python3-gi gir1.2-atspi-2.0 portaudio19-dev libsndfile1
4058```
4159
42- ## 安装
60+ ### 2) Install VibeMouse
4361
4462``` bash
4563python3 -m venv .venv
@@ -48,88 +66,158 @@ pip install -U pip
4866pip install -e .
4967```
5068
51- ## 运行
69+ ### 3) Run (recommended stable mode)
5270
5371``` bash
72+ export VIBEMOUSE_BACKEND=auto
73+ export VIBEMOUSE_DEVICE=cpu
5474vibemouse
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