vocalis 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vocalis-0.1.0/PKG-INFO +230 -0
- vocalis-0.1.0/README.md +202 -0
- vocalis-0.1.0/pyproject.toml +56 -0
- vocalis-0.1.0/pyproject.toml.orig +47 -0
- vocalis-0.1.0/src/vocalis/__init__.py +6 -0
- vocalis-0.1.0/src/vocalis/audio/__init__.py +7 -0
- vocalis-0.1.0/src/vocalis/audio/chime.py +77 -0
- vocalis-0.1.0/src/vocalis/audio/recorder.py +169 -0
- vocalis-0.1.0/src/vocalis/audio/vad.py +112 -0
- vocalis-0.1.0/src/vocalis/cli.py +496 -0
- vocalis-0.1.0/src/vocalis/config.py +157 -0
- vocalis-0.1.0/src/vocalis/core.py +246 -0
- vocalis-0.1.0/src/vocalis/groq/__init__.py +14 -0
- vocalis-0.1.0/src/vocalis/groq/client.py +31 -0
- vocalis-0.1.0/src/vocalis/groq/prompts.py +41 -0
- vocalis-0.1.0/src/vocalis/groq/refiner.py +96 -0
- vocalis-0.1.0/src/vocalis/groq/transcriber.py +62 -0
- vocalis-0.1.0/src/vocalis/output/__init__.py +6 -0
- vocalis-0.1.0/src/vocalis/output/clipboard.py +105 -0
- vocalis-0.1.0/src/vocalis/output/injector.py +86 -0
- vocalis-0.1.0/src/vocalis/ui/__init__.py +21 -0
- vocalis-0.1.0/src/vocalis/ui/display.py +119 -0
vocalis-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: vocalis
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Wispr Flow-inspired AI voice dictation and code formatting CLI using Groq
|
|
5
|
+
Keywords: voice,dictation,whisper,groq,cli,speech-to-text,developer-tools,wispr-flow
|
|
6
|
+
Author: Ishan Bhat
|
|
7
|
+
Author-email: Ishan Bhat <ishan2003bhat@gmail.com>
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development
|
|
15
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
16
|
+
Requires-Dist: click>=8.5.1
|
|
17
|
+
Requires-Dist: groq>=1.7.0
|
|
18
|
+
Requires-Dist: numpy>=2.5.4
|
|
19
|
+
Requires-Dist: pynput>=1.8.2
|
|
20
|
+
Requires-Dist: rich>=15.0.0
|
|
21
|
+
Requires-Dist: scipy>=1.18.1
|
|
22
|
+
Requires-Dist: soundcard>=0.4.6
|
|
23
|
+
Requires-Python: >=3.12
|
|
24
|
+
Project-URL: Homepage, https://github.com/bhatishan2003/vocalis
|
|
25
|
+
Project-URL: Repository, https://github.com/bhatishan2003/vocalis
|
|
26
|
+
Project-URL: Issues, https://github.com/bhatishan2003/vocalis/issues
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# 🎙️ Vocalis
|
|
30
|
+
|
|
31
|
+
> **A Wispr Flow–inspired, ultra-fast AI voice dictation and code formatting CLI for developers, powered by Groq & `uv`.**
|
|
32
|
+
|
|
33
|
+
Vocalis brings the magic of modern voice dictation into your terminal and editor. Speak naturally—mumbling, hesitating, or dictating code—and Vocalis transcribes your voice in **~200ms** via Groq Whisper, removes all filler words (*"um"*, *"ah"*, *"like"*), formats your speech into clean prose or syntax-highlighted code with Llama 3.3, and copies it straight to your clipboard using **OSC 52** and native system clipboards.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## ✨ Features
|
|
38
|
+
|
|
39
|
+
- **⚡ Sub-Second Latency**: Powered by Groq's high-speed Whisper (`whisper-large-v3-turbo`) and `openai/gpt-oss-120b` (or `llama-3.3-70b-versatile`).
|
|
40
|
+
- **🧠 Wispr Flow AI Refinement**: Automatically cleans disfluencies, false starts, and repetitions while preserving your exact intent.
|
|
41
|
+
- **🎯 4 Tailored Modes**:
|
|
42
|
+
- `prose` (Default): Clean, professional prose for comments, docs, commit messages, and emails.
|
|
43
|
+
- `code`: Understands programming idioms (`camelCase`, `snake_case`, functions, indentation, syntax).
|
|
44
|
+
- `prompt`: Transforms spoken brainstorming into structured prompts for AI assistants (Cursor, Claude, Copilot).
|
|
45
|
+
- `raw`: Verbatim Whisper transcription without LLM post-processing.
|
|
46
|
+
- **🎙️ Zero-Lag Voice Activity Detection (VAD)**: Dynamic noise-floor calibration detects when you start and stop speaking automatically.
|
|
47
|
+
- **📋 Universal Clipboard Injection**: Supports **OSC 52** (works natively inside VS Code, Cursor, Neovim, tmux, Alacritty, Kitty, WezTerm) alongside Wayland (`wl-copy`) and X11 (`xclip`).
|
|
48
|
+
- **📦 Managed with `uv`**: Ultra-fast packaging, deterministic virtualenvs, and simple execution.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## 🚀 Quick Start
|
|
53
|
+
|
|
54
|
+
### 1. Installation
|
|
55
|
+
|
|
56
|
+
Clone and sync the project with [`uv`](https://github.com/astral-sh/uv):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd vocalis
|
|
60
|
+
uv sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
To run `vocalis` from anywhere, add an alias to your shell profile (`~/.bashrc` or `~/.zshrc`):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
alias vocalis="uv run --directory /home/ishan/vocalis vocalis"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Or install it globally using `uv tool`:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
uv tool install .
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### 2. Configure Your Groq API Key
|
|
78
|
+
|
|
79
|
+
Set your Groq key via the CLI (saved in `~/.config/vocalis/config.json`):
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
vocalis config set groq_api_key gsk_YOUR_GROQ_API_KEY
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or export the standard environment variable:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
export GROQ_API_KEY="gsk_YOUR_GROQ_API_KEY"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### 3. Test Your Microphone
|
|
94
|
+
|
|
95
|
+
Run the live visual VU meter to verify your audio input:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
vocalis test-mic
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 💻 Usage
|
|
104
|
+
|
|
105
|
+
### Basic Dictation
|
|
106
|
+
Start listening in your terminal or editor split:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
vocalis start
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Speak your thoughts naturally. When you finish speaking, Vocalis automatically detects silence, processes the audio through Groq, prints the result card, and copies the refined text to your clipboard.
|
|
113
|
+
|
|
114
|
+
### One-Shot Mode (Best for Editor Keybindings)
|
|
115
|
+
Record a single thought, copy to clipboard, and exit:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
vocalis start --once
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Dictate Code
|
|
122
|
+
Converts verbal programming into clean syntax:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
vocalis start --mode code
|
|
126
|
+
```
|
|
127
|
+
> **You say:** *"Make an async function called fetch user that takes user id as an int and returns a dictionary"*
|
|
128
|
+
> **Vocalis writes:** `async def fetch_user(user_id: int) -> dict:`
|
|
129
|
+
|
|
130
|
+
### Dictate Prompts for AI Coding Assistants
|
|
131
|
+
Converts rambling ideas into structured prompts:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
vocalis start --mode prompt
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Continuous Loop
|
|
138
|
+
Keep listening for multiple thoughts:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
vocalis start --continuous
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Manual Push-to-Talk
|
|
145
|
+
Ignore silence detection and press **Enter** when you're done speaking:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
vocalis start --manual
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Quiet / Direct Pipe Mode
|
|
152
|
+
Output only the final text to stdout (ideal for shell piping):
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
vocalis start --once --quiet > draft.txt
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 🛠️ Editor Integration
|
|
161
|
+
|
|
162
|
+
Run `vocalis setup-editor` to view configuration snippets for your editor:
|
|
163
|
+
|
|
164
|
+
### VS Code / Cursor Integration
|
|
165
|
+
|
|
166
|
+
1. In `.vscode/tasks.json` (or User Tasks `Ctrl+Shift+P` → `Tasks: Open User Tasks`):
|
|
167
|
+
```json
|
|
168
|
+
{
|
|
169
|
+
"version": "2.0.0",
|
|
170
|
+
"tasks": [
|
|
171
|
+
{
|
|
172
|
+
"label": "Vocalis: Dictate",
|
|
173
|
+
"type": "shell",
|
|
174
|
+
"command": "uv run --directory /home/ishan/vocalis vocalis start --once",
|
|
175
|
+
"presentation": {
|
|
176
|
+
"reveal": "always",
|
|
177
|
+
"panel": "shared",
|
|
178
|
+
"focus": true
|
|
179
|
+
},
|
|
180
|
+
"problemMatcher": []
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
2. In `keybindings.json` (`Ctrl+Shift+P` → `Preferences: Open Keyboard Shortcuts (JSON)`):
|
|
187
|
+
```json
|
|
188
|
+
[
|
|
189
|
+
{
|
|
190
|
+
"key": "ctrl+alt+v",
|
|
191
|
+
"command": "workbench.action.tasks.runTask",
|
|
192
|
+
"args": "Vocalis: Dictate"
|
|
193
|
+
}
|
|
194
|
+
]
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Now pressing `Ctrl+Alt+V` in VS Code starts listening, and the moment you pause, the result is in your clipboard ready to paste!
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
## ⚙️ Configuration Reference
|
|
201
|
+
|
|
202
|
+
Inspect your current configuration:
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
vocalis config show
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Update any setting with `vocalis config set <key> <value>`:
|
|
209
|
+
|
|
210
|
+
| Key | Default | Description |
|
|
211
|
+
| :--- | :--- | :--- |
|
|
212
|
+
| `groq_api_key` | `None` | Your Groq API key |
|
|
213
|
+
| `default_mode` | `prose` | Default mode: `prose`, `code`, `prompt`, `raw` |
|
|
214
|
+
| `stt_model` | `whisper-large-v3-turbo` | Groq Whisper model |
|
|
215
|
+
| `llm_model` | `openai/gpt-oss-120b` | Groq LLM model (`openai/gpt-oss-120b`, `llama-3.3-70b-versatile`, etc.) |
|
|
216
|
+
| `silence_duration` | `0.9` | Seconds of silence before auto-finishing recording |
|
|
217
|
+
| `energy_threshold` | `0.012` | Voice activity detection RMS threshold |
|
|
218
|
+
| `language` | `en` | Speech language code (`en`, `es`, `fr`, or `auto`) |
|
|
219
|
+
| `auto_copy` | `True` | Automatically copy output to clipboard |
|
|
220
|
+
| `input_device` | `None` | Audio input device (run `vocalis list-devices`) |
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## 🧪 Testing
|
|
225
|
+
|
|
226
|
+
Run the test suite with `uv`:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
uv run pytest
|
|
230
|
+
```
|
vocalis-0.1.0/README.md
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# 🎙️ Vocalis
|
|
2
|
+
|
|
3
|
+
> **A Wispr Flow–inspired, ultra-fast AI voice dictation and code formatting CLI for developers, powered by Groq & `uv`.**
|
|
4
|
+
|
|
5
|
+
Vocalis brings the magic of modern voice dictation into your terminal and editor. Speak naturally—mumbling, hesitating, or dictating code—and Vocalis transcribes your voice in **~200ms** via Groq Whisper, removes all filler words (*"um"*, *"ah"*, *"like"*), formats your speech into clean prose or syntax-highlighted code with Llama 3.3, and copies it straight to your clipboard using **OSC 52** and native system clipboards.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- **⚡ Sub-Second Latency**: Powered by Groq's high-speed Whisper (`whisper-large-v3-turbo`) and `openai/gpt-oss-120b` (or `llama-3.3-70b-versatile`).
|
|
12
|
+
- **🧠 Wispr Flow AI Refinement**: Automatically cleans disfluencies, false starts, and repetitions while preserving your exact intent.
|
|
13
|
+
- **🎯 4 Tailored Modes**:
|
|
14
|
+
- `prose` (Default): Clean, professional prose for comments, docs, commit messages, and emails.
|
|
15
|
+
- `code`: Understands programming idioms (`camelCase`, `snake_case`, functions, indentation, syntax).
|
|
16
|
+
- `prompt`: Transforms spoken brainstorming into structured prompts for AI assistants (Cursor, Claude, Copilot).
|
|
17
|
+
- `raw`: Verbatim Whisper transcription without LLM post-processing.
|
|
18
|
+
- **🎙️ Zero-Lag Voice Activity Detection (VAD)**: Dynamic noise-floor calibration detects when you start and stop speaking automatically.
|
|
19
|
+
- **📋 Universal Clipboard Injection**: Supports **OSC 52** (works natively inside VS Code, Cursor, Neovim, tmux, Alacritty, Kitty, WezTerm) alongside Wayland (`wl-copy`) and X11 (`xclip`).
|
|
20
|
+
- **📦 Managed with `uv`**: Ultra-fast packaging, deterministic virtualenvs, and simple execution.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🚀 Quick Start
|
|
25
|
+
|
|
26
|
+
### 1. Installation
|
|
27
|
+
|
|
28
|
+
Clone and sync the project with [`uv`](https://github.com/astral-sh/uv):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd vocalis
|
|
32
|
+
uv sync
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To run `vocalis` from anywhere, add an alias to your shell profile (`~/.bashrc` or `~/.zshrc`):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
alias vocalis="uv run --directory /home/ishan/vocalis vocalis"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or install it globally using `uv tool`:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv tool install .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### 2. Configure Your Groq API Key
|
|
50
|
+
|
|
51
|
+
Set your Groq key via the CLI (saved in `~/.config/vocalis/config.json`):
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
vocalis config set groq_api_key gsk_YOUR_GROQ_API_KEY
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or export the standard environment variable:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
export GROQ_API_KEY="gsk_YOUR_GROQ_API_KEY"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### 3. Test Your Microphone
|
|
66
|
+
|
|
67
|
+
Run the live visual VU meter to verify your audio input:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
vocalis test-mic
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 💻 Usage
|
|
76
|
+
|
|
77
|
+
### Basic Dictation
|
|
78
|
+
Start listening in your terminal or editor split:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
vocalis start
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Speak your thoughts naturally. When you finish speaking, Vocalis automatically detects silence, processes the audio through Groq, prints the result card, and copies the refined text to your clipboard.
|
|
85
|
+
|
|
86
|
+
### One-Shot Mode (Best for Editor Keybindings)
|
|
87
|
+
Record a single thought, copy to clipboard, and exit:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
vocalis start --once
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Dictate Code
|
|
94
|
+
Converts verbal programming into clean syntax:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
vocalis start --mode code
|
|
98
|
+
```
|
|
99
|
+
> **You say:** *"Make an async function called fetch user that takes user id as an int and returns a dictionary"*
|
|
100
|
+
> **Vocalis writes:** `async def fetch_user(user_id: int) -> dict:`
|
|
101
|
+
|
|
102
|
+
### Dictate Prompts for AI Coding Assistants
|
|
103
|
+
Converts rambling ideas into structured prompts:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
vocalis start --mode prompt
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Continuous Loop
|
|
110
|
+
Keep listening for multiple thoughts:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
vocalis start --continuous
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Manual Push-to-Talk
|
|
117
|
+
Ignore silence detection and press **Enter** when you're done speaking:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
vocalis start --manual
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Quiet / Direct Pipe Mode
|
|
124
|
+
Output only the final text to stdout (ideal for shell piping):
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
vocalis start --once --quiet > draft.txt
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 🛠️ Editor Integration
|
|
133
|
+
|
|
134
|
+
Run `vocalis setup-editor` to view configuration snippets for your editor:
|
|
135
|
+
|
|
136
|
+
### VS Code / Cursor Integration
|
|
137
|
+
|
|
138
|
+
1. In `.vscode/tasks.json` (or User Tasks `Ctrl+Shift+P` → `Tasks: Open User Tasks`):
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"version": "2.0.0",
|
|
142
|
+
"tasks": [
|
|
143
|
+
{
|
|
144
|
+
"label": "Vocalis: Dictate",
|
|
145
|
+
"type": "shell",
|
|
146
|
+
"command": "uv run --directory /home/ishan/vocalis vocalis start --once",
|
|
147
|
+
"presentation": {
|
|
148
|
+
"reveal": "always",
|
|
149
|
+
"panel": "shared",
|
|
150
|
+
"focus": true
|
|
151
|
+
},
|
|
152
|
+
"problemMatcher": []
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
2. In `keybindings.json` (`Ctrl+Shift+P` → `Preferences: Open Keyboard Shortcuts (JSON)`):
|
|
159
|
+
```json
|
|
160
|
+
[
|
|
161
|
+
{
|
|
162
|
+
"key": "ctrl+alt+v",
|
|
163
|
+
"command": "workbench.action.tasks.runTask",
|
|
164
|
+
"args": "Vocalis: Dictate"
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Now pressing `Ctrl+Alt+V` in VS Code starts listening, and the moment you pause, the result is in your clipboard ready to paste!
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
## ⚙️ Configuration Reference
|
|
173
|
+
|
|
174
|
+
Inspect your current configuration:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
vocalis config show
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Update any setting with `vocalis config set <key> <value>`:
|
|
181
|
+
|
|
182
|
+
| Key | Default | Description |
|
|
183
|
+
| :--- | :--- | :--- |
|
|
184
|
+
| `groq_api_key` | `None` | Your Groq API key |
|
|
185
|
+
| `default_mode` | `prose` | Default mode: `prose`, `code`, `prompt`, `raw` |
|
|
186
|
+
| `stt_model` | `whisper-large-v3-turbo` | Groq Whisper model |
|
|
187
|
+
| `llm_model` | `openai/gpt-oss-120b` | Groq LLM model (`openai/gpt-oss-120b`, `llama-3.3-70b-versatile`, etc.) |
|
|
188
|
+
| `silence_duration` | `0.9` | Seconds of silence before auto-finishing recording |
|
|
189
|
+
| `energy_threshold` | `0.012` | Voice activity detection RMS threshold |
|
|
190
|
+
| `language` | `en` | Speech language code (`en`, `es`, `fr`, or `auto`) |
|
|
191
|
+
| `auto_copy` | `True` | Automatically copy output to clipboard |
|
|
192
|
+
| `input_device` | `None` | Audio input device (run `vocalis list-devices`) |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 🧪 Testing
|
|
197
|
+
|
|
198
|
+
Run the test suite with `uv`:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
uv run pytest
|
|
202
|
+
```
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "vocalis"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Wispr Flow-inspired AI voice dictation and code formatting CLI using Groq"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"click>=8.5.1",
|
|
9
|
+
"groq>=1.7.0",
|
|
10
|
+
"numpy>=2.5.4",
|
|
11
|
+
"pynput>=1.8.2",
|
|
12
|
+
"rich>=15.0.0",
|
|
13
|
+
"scipy>=1.18.1",
|
|
14
|
+
"soundcard>=0.4.6",
|
|
15
|
+
]
|
|
16
|
+
keywords = [
|
|
17
|
+
"voice",
|
|
18
|
+
"dictation",
|
|
19
|
+
"whisper",
|
|
20
|
+
"groq",
|
|
21
|
+
"cli",
|
|
22
|
+
"speech-to-text",
|
|
23
|
+
"developer-tools",
|
|
24
|
+
"wispr-flow",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 4 - Beta",
|
|
28
|
+
"Environment :: Console",
|
|
29
|
+
"Intended Audience :: Developers",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Topic :: Software Development",
|
|
33
|
+
"Topic :: Multimedia :: Sound/Audio :: Speech",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[[project.authors]]
|
|
37
|
+
name = "Ishan Bhat"
|
|
38
|
+
email = "ishan2003bhat@gmail.com"
|
|
39
|
+
|
|
40
|
+
[project.license]
|
|
41
|
+
text = "MIT"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/bhatishan2003/vocalis"
|
|
45
|
+
Repository = "https://github.com/bhatishan2003/vocalis"
|
|
46
|
+
Issues = "https://github.com/bhatishan2003/vocalis/issues"
|
|
47
|
+
|
|
48
|
+
[project.scripts]
|
|
49
|
+
vocalis = "vocalis:main"
|
|
50
|
+
|
|
51
|
+
[build-system]
|
|
52
|
+
requires = ["uv_build>=0.12.20,<0.13.0"]
|
|
53
|
+
build-backend = "uv_build"
|
|
54
|
+
|
|
55
|
+
[dependency-groups]
|
|
56
|
+
dev = ["pytest>=9.2.0"]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "vocalis"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Wispr Flow-inspired AI voice dictation and code formatting CLI using Groq"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Ishan Bhat", email = "ishan2003bhat@gmail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"click>=8.5.1",
|
|
12
|
+
"groq>=1.7.0",
|
|
13
|
+
"numpy>=2.5.4",
|
|
14
|
+
"pynput>=1.8.2",
|
|
15
|
+
"rich>=15.0.0",
|
|
16
|
+
"scipy>=1.18.1",
|
|
17
|
+
"soundcard>=0.4.6",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
license = { text = "MIT" }
|
|
21
|
+
keywords = ["voice", "dictation", "whisper", "groq", "cli", "speech-to-text", "developer-tools", "wispr-flow"]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Environment :: Console",
|
|
25
|
+
"Intended Audience :: Developers",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Topic :: Software Development",
|
|
29
|
+
"Topic :: Multimedia :: Sound/Audio :: Speech",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.urls]
|
|
33
|
+
Homepage = "https://github.com/bhatishan2003/vocalis"
|
|
34
|
+
Repository = "https://github.com/bhatishan2003/vocalis"
|
|
35
|
+
Issues = "https://github.com/bhatishan2003/vocalis/issues"
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
vocalis = "vocalis:main"
|
|
39
|
+
|
|
40
|
+
[build-system]
|
|
41
|
+
requires = ["uv_build>=0.12.20,<0.13.0"]
|
|
42
|
+
build-backend = "uv_build"
|
|
43
|
+
|
|
44
|
+
[dependency-groups]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=9.2.0",
|
|
47
|
+
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"""Audio recording, processing, and sound effects module."""
|
|
2
|
+
|
|
3
|
+
from vocalis.audio.chime import ChimePlayer
|
|
4
|
+
from vocalis.audio.recorder import AudioRecorder
|
|
5
|
+
from vocalis.audio.vad import SpeechState, VADDetector
|
|
6
|
+
|
|
7
|
+
__all__ = ["AudioRecorder", "ChimePlayer", "SpeechState", "VADDetector"]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Non-blocking audio cues and earcons for Vocalis."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import io
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import threading
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from scipy.io import wavfile
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ChimePlayer:
|
|
16
|
+
"""Generates and plays lightweight audio chimes for voice state transitions."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, enabled: bool = True) -> None:
|
|
19
|
+
self.enabled = enabled
|
|
20
|
+
self._start_wav: Optional[bytes] = None
|
|
21
|
+
self._done_wav: Optional[bytes] = None
|
|
22
|
+
if self.enabled:
|
|
23
|
+
self._prepare_chimes()
|
|
24
|
+
|
|
25
|
+
def _generate_tone(self, freq: float, duration: float, volume: float = 0.12) -> bytes:
|
|
26
|
+
"""Synthesize a soft sine wave chime with smooth cosine envelope."""
|
|
27
|
+
sample_rate = 16000
|
|
28
|
+
num_samples = int(sample_rate * duration)
|
|
29
|
+
t = np.linspace(0, duration, num_samples, endpoint=False)
|
|
30
|
+
|
|
31
|
+
# Smooth bell envelope (raised cosine) to eliminate clicks
|
|
32
|
+
envelope = np.sin(np.pi * t / duration)
|
|
33
|
+
signal = (envelope * volume * np.sin(2 * np.pi * freq * t) * 32767.0).astype(np.int16)
|
|
34
|
+
|
|
35
|
+
buf = io.BytesIO()
|
|
36
|
+
wavfile.write(buf, sample_rate, signal)
|
|
37
|
+
return buf.getvalue()
|
|
38
|
+
|
|
39
|
+
def _prepare_chimes(self) -> None:
|
|
40
|
+
"""Pre-generate in-memory WAV bytes so playback has zero computational latency."""
|
|
41
|
+
try:
|
|
42
|
+
# Start chime: Pleasant high A5 (880 Hz, 35ms)
|
|
43
|
+
self._start_wav = self._generate_tone(880.0, 0.035, volume=0.10)
|
|
44
|
+
# Done chime: Bright C6 (1046.5 Hz, 45ms)
|
|
45
|
+
self._done_wav = self._generate_tone(1046.5, 0.045, volume=0.10)
|
|
46
|
+
except Exception:
|
|
47
|
+
self.enabled = False
|
|
48
|
+
|
|
49
|
+
def _play_raw(self, wav_bytes: Optional[bytes]) -> None:
|
|
50
|
+
"""Play WAV audio in a subprocess without blocking the main thread."""
|
|
51
|
+
if not self.enabled or not wav_bytes:
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
def worker():
|
|
55
|
+
for cmd in (["aplay", "-q"], ["pw-play", "-"]):
|
|
56
|
+
if shutil.which(cmd[0]):
|
|
57
|
+
try:
|
|
58
|
+
proc = subprocess.Popen(
|
|
59
|
+
cmd,
|
|
60
|
+
stdin=subprocess.PIPE,
|
|
61
|
+
stdout=subprocess.DEVNULL,
|
|
62
|
+
stderr=subprocess.DEVNULL,
|
|
63
|
+
)
|
|
64
|
+
proc.communicate(input=wav_bytes, timeout=0.6)
|
|
65
|
+
return
|
|
66
|
+
except Exception:
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
threading.Thread(target=worker, daemon=True).start()
|
|
70
|
+
|
|
71
|
+
def play_start(self) -> None:
|
|
72
|
+
"""Play cue when speech starts."""
|
|
73
|
+
self._play_raw(self._start_wav)
|
|
74
|
+
|
|
75
|
+
def play_done(self) -> None:
|
|
76
|
+
"""Play cue when processing completes and text is typed."""
|
|
77
|
+
self._play_raw(self._done_wav)
|