Skip to content
 
 

Repository files navigation

linux-voice

Voice-to-text dictation tool for Linux (X11) using OpenAI Whisper.

Hold Ctrl+Space to record speech, release to transcribe and type into the focused window.

Requirements

  • Python 3.11+
  • Linux with X11 (Wayland has limited support)
  • PulseAudio/PipeWire
  • Working microphone
  • OpenAI API key

Installation

Ubuntu/Debian

# System dependencies
sudo apt install xdotool ffmpeg python3-pip python3-venv

# Create virtual environment (recommended)
python3 -m venv ~/.local/share/linux-voice
source ~/.local/share/linux-voice/bin/activate

# Install Python packages
pip install pynput sounddevice numpy openai

# Download and install script
curl -o ~/.local/bin/linux-voice https://raw.githubusercontent.com/williamjameshandley/linux-voice/main/linux-voice.py
chmod +x ~/.local/bin/linux-voice

Fedora

# System dependencies
sudo dnf install xdotool ffmpeg python3-pip

# Create virtual environment (recommended)
python3 -m venv ~/.local/share/linux-voice
source ~/.local/share/linux-voice/bin/activate

# Install Python packages
pip install pynput sounddevice numpy openai

# Download and install script
curl -o ~/.local/bin/linux-voice https://raw.githubusercontent.com/williamjameshandley/linux-voice/main/linux-voice.py
chmod +x ~/.local/bin/linux-voice

Arch Linux

# System dependencies
sudo pacman -S xdotool ffmpeg python-numpy python-pynput python-sounddevice python-openai

# Download and install script
curl -o ~/.local/bin/linux-voice https://raw.githubusercontent.com/williamjameshandley/linux-voice/main/linux-voice.py
chmod +x ~/.local/bin/linux-voice

Or build the package:

git clone https://github.com/williamjameshandley/linux-voice
cd linux-voice
makepkg -si

pip (Any Distribution)

# Ensure system dependencies are installed first:
# - xdotool (for typing text)
# - ffmpeg (for audio compression, optional but recommended)

pip install pynput sounddevice numpy openai

# Download script
curl -o ~/.local/bin/linux-voice https://raw.githubusercontent.com/williamjameshandley/linux-voice/main/linux-voice.py
chmod +x ~/.local/bin/linux-voice

macOS (from scratch)

1. Install system dependencies

brew install ffmpeg uv

2. Clone and set up the project

git clone https://github.com/williamjameshandley/linux-voice
cd linux-voice
uv sync --extra macos --extra groq   # or without --extra groq if using OpenAI

3. Configure

Get a free Groq API key at groq.com (or use an OpenAI key).

mkdir -p ~/.config/linux-voice
cat > ~/.config/linux-voice/config.toml << 'EOF'
[transcription]
backend = "groq"
api_key = "your-groq-api-key-here"
EOF

For OpenAI, omit the backend line and set your OpenAI key as api_key.

4. Grant permissions

  • Accessibility: System Settings > Privacy & Security > Accessibility — add /bin/zsh (click +, press Cmd+Shift+G, type /bin/zsh)
  • Microphone: Will be prompted on first run

5. Test manually

uv run python linux-voice.py

Hold Cmd+Shift+Space, speak, release. Text should appear in the focused window. Press Ctrl+C to stop.

6. Set up auto-start (LaunchAgent)

uv run python linux-voice.py --install-agent

This auto-generates the LaunchAgent plist with the correct paths and API key. Then start it:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.linux-voice.agent.plist

Voice dictation now works globally in any app via Cmd+Shift+Space and starts automatically on login.

Managing the service

# View logs
tail -f ~/Library/Logs/linux-voice.log

# Restart after code changes
launchctl kickstart -k gui/$(id -u)/com.linux-voice.agent

# Uninstall (stop + remove)
uv run python linux-voice.py --uninstall-agent

Default hotkeys on macOS

Hotkey Action
Cmd+Shift+Space Hold to record, release to transcribe
Cmd+Shift+Ctrl+Space Record and auto-press Enter
Cmd+Alt+Space Record correction instruction

API Key Setup (Linux)

Add to your shell profile (~/.bashrc, ~/.zshrc, etc.):

export OPENAI_API_KEY="your-key-here"

For the systemd service, create ~/.config/environment.d/openai.conf:

OPENAI_API_KEY=your-key-here

Usage

Manual

linux-voice

If using a virtual environment:

~/.local/share/linux-voice/bin/python ~/.local/bin/linux-voice

Systemd Service (Auto-start)

Create ~/.config/systemd/user/linux-voice.service:

[Unit]
Description=Linux Voice Dictation

[Service]
ExecStart=%h/.local/bin/linux-voice
Restart=on-failure

[Install]
WantedBy=default.target

If using a virtual environment, update ExecStart:

ExecStart=%h/.local/share/linux-voice/bin/python %h/.local/bin/linux-voice

Then enable:

systemctl --user daemon-reload
systemctl --user enable --now linux-voice

# Check status
systemctl --user status linux-voice

# View logs
journalctl --user -u linux-voice -f

Modes

  • Hold mode (default): Hold Ctrl+Space while speaking, release to transcribe
  • Toggle mode: Press Ctrl+Space to start recording, press again to stop
LINUX_VOICE_MODE=toggle linux-voice

Submit Hotkey

Use Ctrl+Shift+Space (default) to record and automatically press Enter after typing. Useful for command-line input, chat applications, or any context where you want to submit immediately.

Configure an alternative (e.g., Alt+Space) in ~/.config/linux-voice/config.toml:

[hotkey_submit]
key = "space"
modifiers = ["alt"]
delay = 150  # ms delay before Enter (increase if unreliable)

Edit Hotkey

Use Ctrl+Alt+Space (default) to correct the previous transcription using an LLM. This is useful when Whisper misinterprets a word:

  1. Dictate normally with Ctrl+Space → "The function uses a cash mechanism"
  2. Hold Ctrl+Alt+Space and say "change cash to cache"
  3. The original text is cleared and replaced with "The function uses a cache mechanism"

The edit uses the backend's chat model (gpt-4o-mini for OpenAI, llama-3.3-70b-versatile for Groq). The LLM is aware of Unix/programming context and common voice recognition errors (cash→cache, bite→byte, get→git, etc.).

Configure in ~/.config/linux-voice/config.toml:

[hotkey_edit]
key = "space"
modifiers = ["ctrl", "alt"]

[transcription]
# llm_model = "gpt-4o-mini"  # Override LLM model for corrections

Offline Recovery

If the internet connection fails during transcription, the audio is saved and you'll see:

(no internet - say 'recover' to retry)

When internet is restored, hold Ctrl+Space and say "recover" to transcribe the saved audio. The recovery file is stored at /tmp/linux-voice-recovery.wav and deleted after successful recovery.

Voice Commands

Command Action
"recover" Transcribe saved audio from a failed attempt

Configuration

Create ~/.config/linux-voice/config.toml to customize:

[hotkey]
key = "space"
modifiers = ["ctrl"]
mode = "hold"  # or "toggle"

[hotkey_submit]
key = "space"
modifiers = ["ctrl", "shift"]  # Ctrl+Shift+Space by default
delay = 150                     # ms delay before Enter key

[hotkey_edit]
key = "space"
modifiers = ["ctrl", "alt"]    # Ctrl+Alt+Space by default

[audio]
sample_rate = 16000      # Whisper native rate (don't change unless needed)
silence_threshold = 150  # RMS threshold for silence detection

[transcription]
backend = "openai"  # or "groq"
language = "en"
# model = "whisper-1"  # or "whisper-large-v3-turbo" for groq
# llm_model = "gpt-4o-mini"  # or "llama-3.3-70b-versatile" for groq (edit mode)
# prompt = "Domain-specific vocabulary. Technical terms, jargon, names."

Backend Options

Backend Model Cost Latency
openai whisper-1 $0.006/min ~1-2s
groq whisper-large-v3-turbo $0.04/hr ~200ms

For Groq, set GROQ_API_KEY instead of OPENAI_API_KEY.

The prompt helps Whisper with:

  • British vs American spelling (colour, favour, organisation)
  • Domain-specific vocabulary (your field's jargon)
  • Consistent formatting and punctuation

Text Replacements

Define regex replacements to convert spoken phrases into special characters or commands:

[replacements]
"^[Ss]lash " = "/"              # "slash compact" → "/compact"
"^[Ff]orward [Ss]lash " = "/"
"^(/.*)\\.\\s*$" = "\\1"        # strip period only from /commands

This allows saying "slash compact" to type /compact for Claude Code commands.

Privacy and Security

Audio is sent to OpenAI: All recorded speech is transmitted to OpenAI's Whisper API for transcription. See OpenAI's data usage policies.

Text is typed into the focused window: Be careful not to dictate sensitive information while password fields or sensitive applications are focused.

Cost

OpenAI Whisper API costs $0.006 per minute of audio. A typical 10-second dictation costs ~$0.001.

Troubleshooting

Microphone not working

Ubuntu/Debian:

sudo apt install linux-firmware

Fedora:

sudo dnf install linux-firmware

Arch Linux (modern AMD laptops - Ryzen 6000+, Strix Point):

sudo pacman -S sof-firmware

Then reboot.

Vim

Ctrl+Space (C-@) has a default behavior in vim insert mode (insert previously inserted text). Disable it by adding to your .vimrc:

" Disable Ctrl+Space insert mode behavior (for linux-voice)
inoremap <C-@> <Nop>

Wayland

xdotool has limited Wayland support. Consider using X11 or switching to ydotool.

Permission errors with pynput

On some systems, you may need to run as root or add your user to the input group:

sudo usermod -aG input $USER

Then log out and back in.

macOS: Hotkeys not working

  • Accessibility permissions: Ensure your terminal app is listed in System Settings > Privacy & Security > Accessibility. Remove and re-add it if permissions were reset after a macOS update.
  • Secure Input Mode: When a password field is focused or sudo is running in terminal, macOS enables Secure Input which blocks global hotkey monitoring. Switch to a different window/app.
  • Spotlight conflict: The default Cmd+Space is taken by Spotlight. linux-voice defaults to Cmd+Shift+Space on macOS to avoid this.

macOS: Text not appearing

  • Text is injected via clipboard paste (Cmd+V). If the target app blocks paste, text injection will fail.
  • Some terminal apps (iTerm2) may prompt before pasting multi-line text.

License

MIT

About

Voice-to-text dictation tool for Linux (X11) using OpenAI Whisper

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages