6b14338d1e feat(tray): offer the recommended model from the missing-model notification (#687)
* feat(tray): offer the recommended model from the missing-model notification

Dictation without a model on disk showed a dead-end notification telling
the user to open Settings, find the model picker and start the download
by hand, at the moment they wanted to talk. There was no Download button
anywhere: downloads only happen as a side effect of changing a selection.

The notification now carries a "Download <model> (<size>)" button for the
model the picker already stars for this machine, so recommendations stay
in one place: get_recommended_model() for whisper.cpp, including the
English-only variant when an English language is selected, and the RAM
based recommendations for VOSK and Whisper. Clicking it downloads in the
background, reports progress in the notification, and saves the model for
that engine only after it loaded.

Notification servers that do not advertise the actions capability, and
systems without libnotify, still get the plain text they got before.
Dictation is not started for the user afterwards: a download can take
several minutes, and grabbing the microphone unannounced would surprise
someone who has long since moved on.

* feat(tray): actually fetch the offered model, and only claim it when loaded

Review follow-ups on #687.

reconfigure() only re-initializes when engine, model or language change,
and force_download is read during that re-init. First-run defaults are
whisper_cpp + tiny, and tiny is what get_recommended_model() returns on a
CPU-only machine under 16GB, so the click was a no-op that logged
"Applied VAD/silence timeout changes.", saved the model, said "Speech
model ready", and left the next shortcut showing the same missing-model
notification.

Add force_reinit to reconfigure() and pass it here, then gate the save
and the success notification on speech_engine.model_ready instead of on
reconfigure() not raising.

The "starting..." notification is now created in
_download_recommended_model, which runs on the main loop where libnotify
dispatches the action; only the handle travels to the worker, which
already routes update/close/notify through _idle_once.

The offer body no longer promises a button the server cannot draw: with
no action it points at Settings, like the notification it replaced.

Tests cover the case that breaks the feature — the recommendation equal
to the configured model — behaviourally, through a stand-in engine that
gates re-init the way reconfigure() does, plus the real reconfigure()
contract in both directions. They also stop touching sys.modules at
collection time, which is the desync #686 hit, and black is clean.

* test(notifications): cover the libnotify/notify-send boundary directly

Every test that touches notifications so far patches the whole module
away, so the module itself had no coverage: the fallback to notify-send
when the server has no action support or libnotify fails to initialize,
the handle kept alive in _pending until the user answers, and update()
refusing a fallback handle. These drive it with a fake Notify installed
through the module's own lazy cache rather than by patching
gi.repository, which is shared with every other test in the process.

* fix(download): allow only one model download at a time across tray and Settings

The tray's download worker and the Settings dialog's both drive the same
engine, which has a single progress callback slot and a single
configuration. Started together, the later one overwrote the earlier
one's progress callback, the earlier one's finally block then cleared it
mid-download, and whichever finished last became the persisted model.

Give the engine a non-blocking claim. Both Settings entry points and the
tray take it before starting a download and release it when the worker
ends; whoever loses the race is told a download is already running and
the Settings picker goes back to the saved model.

---------

Co-authored-by: Kacper Paczos <23406555+kacperpaczos@users.noreply.github.com>
2026-08-28 23:29:58 -07:00
2025-05-25 23:20:08 -05:00
2026-08-23 01:33:08 -07:00

Vocalinux

Vocalinux

Voice-to-text for Linux, finally done right!

Privacy: on-device X11 & Wayland PRs Welcome License: AGPL-3.0 Python 3.11+ Discord Email VocaHQ

GitHub release PyPI AUR Vocalinux CI codecov Follow on X

Ubuntu Debian Fedora Arch openSUSE

Linux has always punched above its weight, except when it comes to voice typing. Vocalinux fixes that.

It's a free, AGPL-3.0-licensed desktop app that lets you dictate text into any application, on X11 or Wayland, using on-device speech recognition after you download a model. Pick from three engines (whisper.cpp, OpenAI Whisper, or VOSK), get automatic GPU acceleration via Vulkan, and control it all with customizable keyboard shortcuts: toggle or push-to-talk.

Models are downloaded once. After that, speech-to-text stays on your machine. No Voca account is required. Just speak and type.

📚 What's New in v0.16.0

0.16.0 adds an in-app update checker with tray notifications, defaults new installs to hold Right Alt push-to-talk, makes the language list searchable, lets you delete unused downloaded models, and adds a family dictation tone picker. The project license is AGPL-3.0. The installer is hardened (Justfile, uv lockfiles, distro python3-gi). The app icon, tray states, and site favicons use the shared Voca family mic.

Highlights

Feature Description
Update checker Settings → About checks stable/nightly channels; tray shows Update Available when GitHub has a newer release (#631, #645)
Right Alt PTT default New installs default to hold Right Alt (push-to-talk); existing configs keep their shortcut (#648)
Searchable languages Type to filter the Speech Model language list (#672)
Delete unused models Remove leftover downloaded speech models from Settings (#671)
AGPL-3.0 License aligned with other VocaHQ projects (#660)
Family mic icons App icon, tray states, and site favicons use the shared Voca family mic (#704)
Tone picker Settings → Audio: Lift, Flick, Ember, Step, Voca, Soft, Chirp, Scale, Drop, Glass, Off, plus Preview. New installs default to Voca. Catalog uses family preview WAVs (#707, #708)
Installer Justfile, uv lockfiles, distro python3-gi required (no pip sdist of PyGObject). Epic #701 still open (#700, #705, #706)

Also in this release

  • IBus: safer scoped injection, engine restore after teardown, XKB layout restore on X11 (#623, #643, #665)
  • Audio: filter unsafe virtual capture devices; open stereo mics at native channel count; catalog tones are the family preview WAVs, not the synthesized #707 files (#629, #673, #708)
  • Clipboard: restore after ydotool paste; text-only reads and safer overlapping restore (#588, #646)
  • GPU / AppImage: honor bundled GPU libs and skip software Vulkan; ship transitive GI typelibs (AppImage fix already hotfixed onto the v0.15.0 AppImages) (#674, #637)
  • Settings / tray: separate Close from Test Dictation; reuse Settings/Logs windows; prefer Ayatana AppIndicator on KDE; optional missing-tray warning toggle (#670, #669, #621, #628)
  • Test Dictation: no longer reports no speech when recognition never started (#702)
  • Settings: About page groups this app, the VocaHQ family, and talk-to-us links (#718)
  • Installer / downloads / tests: gate util-linux-extra to Ubuntu 24.04+; report failed model downloads; stop tests from overwriting real config.json (#635, #690, #694)
  • Website: vocalinux.com restyled to the Voca family workbench; Discord and X links point at VocaHQ (#728, #729, #722, #717)

See docs/UPDATE.md and the full changelog.


Features

  • 🎤 Toggle or Push-to-Talk activation modes
  • ⚡ Real-time transcription with minimal latency
  • 🌎 Universal compatibility across all Linux applications
  • 🔒 On-device after model download — speech-to-text stays on your machine
  • 🤖 whisper.cpp by default - High-performance C++ speech recognition
  • 🎮 Universal GPU support - Vulkan acceleration for AMD, Intel, and NVIDIA
  • 🎨 System tray integration with visual status indicators
  • 🚀 Start on login support via XDG autostart (desktop-session startup)
  • 🔊 Pleasant audio feedback - smooth gliding tones, headphone-friendly
  • ⚙️ Graphical settings dialog for easy configuration
  • 📦 3 engine choices - whisper.cpp (default), OpenAI Whisper, or VOSK

📸 Screenshots

Vocalinux in action. Settings gallery shots may lag the newest UI. Full gallery on the website screenshots page.

Product

Transcription in Action
Real-time voice-to-text transcription
System Tray
System tray with listening indicator
About View
About & Updates in Settings
Log Viewer
Log viewer for debugging

Settings

Speech Engine settings
Speech Engine
Recognition settings
Recognition
Audio settings
Audio
Performance settings
Performance
General settings
General
Advanced tuning and settings
Advanced

🚀 Quick Install

Our new interactive installer guides you through setup with intelligent hardware detection:

curl -fsSL raw.githubusercontent.com/VocaHQ/vocalinux/main/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh

Choose your engine:

  1. whisper.cpp ⭐ (Recommended) - Fast, works with any GPU via Vulkan
  2. Whisper (OpenAI) - PyTorch-based, NVIDIA GPU only
  3. VOSK - Lightweight, works on older systems

The installer will:

  • Auto-detect your hardware (GPU, RAM, Vulkan support)
  • Recommend the best engine for your system
  • Download the appropriate model (~74MB for the default whisper.cpp tiny model)
  • Install neural VAD support when ONNX Runtime is available
  • Install in ~1-2 minutes (vs 5-10 min with old Whisper)

Note

: Always installs the latest release. For a specific version, check GitHub Releases.

Installation Options

Default (whisper.cpp - recommended):

curl -fsSL raw.githubusercontent.com/VocaHQ/vocalinux/main/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh

Fastest installation (~1-2 min), universal GPU support via Vulkan.

Whisper (OpenAI) - if you prefer PyTorch:

curl -fsSL raw.githubusercontent.com/VocaHQ/vocalinux/main/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh --engine=whisper

NVIDIA GPU only (~5-10 min, downloads PyTorch + CUDA).

VOSK only - for low-RAM systems:

curl -fsSL raw.githubusercontent.com/VocaHQ/vocalinux/main/install.sh -o /tmp/vl.sh && bash /tmp/vl.sh --engine=vosk

Lightweight option (~40MB), works on systems with 4GB RAM.

Arch Linux (AUR)

yay -S vocalinux

See docs/AUR.md.

Flatpak (any distro)

For a sandboxed, distro-independent install (great for NixOS, Fedora Silverblue, Steam Deck, and anywhere else), build the Flatpak from the bundled manifest:

flatpak install flathub org.gnome.Platform//50 org.gnome.Sdk//50
flatpak-builder --user --install --force-clean build-dir \
  packaging/flatpak/com.vocalinux.Vocalinux.yml
flatpak run com.vocalinux.Vocalinux

The Flatpak ships the whisper.cpp engine with Vulkan GPU support and runs through XWayland on Wayland sessions. See packaging/flatpak/README.md for build details, permissions, and Flathub submission notes. Flathub publishing is in progress.

Alternative: Install from Source

# Clone the repository
git clone https://github.com/VocaHQ/vocalinux.git
cd vocalinux

# Run the interactive installer (engine picker + GPU detection)
./install.sh

# Or pick the engine up front
./install.sh --engine=whisper_cpp   # whisper.cpp (default, GPU-accelerated)
./install.sh --engine=vosk          # lightweight VOSK

The installer handles everything: system dependencies, Python environment, speech models, and desktop integration.

🌙 Nightly Releases (Bleeding Edge)

For developers and early adopters who want to test the latest features, check out our GitHub Releases page which includes both beta and nightly builds.

⚠️ Warning: Nightly releases contain the absolute latest code and may be unstable. For production use, we recommend using the latest beta release.

Nightly builds are automatically generated from the main branch every day. They include all merged changes but haven't undergone the same testing as beta releases.

Release Channels:

  • Beta (Recommended) - Tested pre-releases with known features
  • Nightly - Untested bleeding edge with latest commits

After Installation

# If ~/.local/bin is in your PATH (recommended):
vocalinux

# Or activate the virtual environment first:
source ~/.local/bin/activate-vocalinux.sh
vocalinux

# Or run directly:
~/.local/share/vocalinux/venv/bin/vocalinux

Or launch it from your application menu!

📋 Requirements

  • OS: Linux (tested on Ubuntu 24.04+, Debian 12+, Fedora 39+, Arch Linux, openSUSE Tumbleweed)
  • Python: 3.11 or newer
  • Display: X11 or Wayland
  • Hardware: Microphone for voice input

Note: See Distribution Compatibility for distribution-specific information and experimental support for Gentoo, Alpine, Void, Solus, and more.

🎙️ Usage

Voice Dictation

  1. Push-to-talk (default): Hold Right Alt (Option on Mac-layout keyboards) and speak
  2. Speak clearly into your microphone
  3. Release the key to stop, or switch to Toggle mode in Settings (double-tap a key to start/stop)

Voice Commands

Command Action
"new line" Inserts a line break
"period" / "full stop" Types a period (.)
"comma" Types a comma (,)
"question mark" Types a question mark (?)
"exclamation mark" Types an exclamation mark (!)
"delete that" Deletes the last sentence
"capitalize" Capitalizes the next word

Command Line Options

vocalinux --help                  # Show all options
vocalinux --debug                 # Enable debug logging
vocalinux --engine whisper_cpp    # Use whisper.cpp engine (default)
vocalinux --engine whisper        # Use OpenAI Whisper engine
vocalinux --engine vosk           # Use VOSK engine
vocalinux --model medium          # Use medium-sized model
vocalinux --model medium.en-q5_0  # Use exact whisper.cpp model variant
vocalinux --model large-v3-turbo  # Use large-v3 Turbo with whisper.cpp
vocalinux --wayland               # Force Wayland mode
vocalinux --start-minimized       # Start without first-run modal prompts

Autostart on Login

Vocalinux uses the Linux desktop standard for autostart:

  • Mechanism: XDG autostart desktop entry (vocalinux.desktop)
  • Path: $XDG_CONFIG_HOME/autostart/ or ~/.config/autostart/ (fallback)
  • Launch mode: Starts as a regular user desktop app in your graphical session
  • Not used: No systemd unit/service is created by Vocalinux for autostart

How to enable/disable:

  • First-run welcome dialog
  • Tray menu: Start on Login
  • Settings dialog: Start on Login

Compatibility notes:

  • Works on mainstream desktop environments (GNOME, KDE, Xfce, Cinnamon, MATE, LXQt)
  • On minimal/custom window-manager sessions, an autostart handler may be required (for example DE-specific startup hooks or tools like dex)

⚙️ Configuration

Configuration is stored in ~/.config/vocalinux/config.json:

{
  "speech_recognition": {
    "engine": "whisper_cpp",
    "model_size": "tiny",
    "vad_sensitivity": 3,
    "silence_timeout": 2.0
  }
}

For whisper.cpp, model_size may be a size such as tiny or an exact ggml model ID such as medium.en-q5_0 or large-v3-turbo. You can also configure this through the graphical Settings dialog, where whisper.cpp models are split into Model Size and Specialization controls. Unused leftover downloads can be deleted from Unused downloads on the Speech Model page (expand the section, then delete one model at a time).

Neural Voice Activity Detection

Vocalinux ships with a Silero VAD model and uses it automatically when onnxruntime is available. The official installer attempts to install this support automatically. Without it, recording falls back to the simpler amplitude-threshold VAD.

For manual or PyPI installs, enable neural VAD with:

pip install "vocalinux[vad]"

Restart Vocalinux after install. The Recognition tab in Settings shows which backend is active. The same vad_sensitivity (1-5) works for both -- it's mapped to a Silero probability threshold internally (1 = 0.8, 5 = 0.3).

🔧 Development Setup

# Clone and install in dev mode
git clone https://github.com/VocaHQ/vocalinux.git
cd vocalinux
./install.sh --dev

# Activate environment
source venv/bin/activate

# Run tests
pytest

# Run from source with debug
python -m vocalinux.main --debug

📁 Project Structure

vocalinux/
├── src/vocalinux/                 # Main application code
│   ├── speech_recognition/        # Speech recognition engines (VOSK, Whisper, whisper.cpp)
│   │   └── recognition_manager.py # Unified engine interface
│   ├── text_injection/            # Text injection (X11/Wayland)
│   ├── ui/                        # GTK UI components
│   └── utils/                     # Utility functions
│       ├── whispercpp_model_info.py   # whisper.cpp model metadata & hardware detection
│       └── vosk_model_info.py         # VOSK model metadata
├── tests/                         # Test suite
├── scripts/                       # Development utilities
│   └── generate_sounds.py         # Sound generation script
├── resources/                     # Icons and sounds
├── docs/                          # Documentation
└── web/                           # Website source

📖 Documentation

Repository mirrors

GitHub is the primary forge for issues, pull requests, CI, and releases.

Role URL
Primary https://github.com/VocaHQ/vocalinux
Read-only mirror (Codeberg) https://codeberg.org/jatinkrmalik/vocalinux

The Codeberg copy is a read-only source backup. Open issues and PRs on GitHub only.

🔊 Sound Customization

Vocalinux uses smooth, pleasant gliding tones for audio feedback:

  • Start: Ascending F4→A4 (0.6s) - positive, uplifting
  • Stop: Descending A4→F4 (0.6s) - resolves completion
  • Error: Lower descending E4→C4 (0.7s) - gentle but noticeable

All sounds use pure sine waves with smoothstep interpolation for buttery smooth pitch transitions - perfect for headphone use!

Regenerate Sounds

To modify or regenerate the notification sounds:

python scripts/generate_sounds.py

This script generates all three sounds using the same smooth glide algorithm. You can edit the frequencies, durations, and amplitudes in the script to customize the sounds to your preference.

🗺️ Roadmap

  • Custom icon design ✅
  • Graphical settings dialog ✅
  • Whisper AI support ✅
  • Multi-language support (FR, DE, RU) ✅
  • whisper.cpp integration (default engine) ✅
  • Vulkan GPU support ✅
  • In-app update mechanism ✅
  • Wayland support via IBus ✅
  • Flatpak packaging ✅ (Flathub submission in progress)
  • Application-specific commands
  • Debian/Ubuntu package (.deb)
  • Voice command customization

🌐 The Voca Ecosystem

Vocalinux is part of VocaHQ. On-device speech-to-text first, one app per platform. Optional VocaGateway is self-hosted and not on-device.

Platform Project Website GitHub Status
🐧 Linux VocaLinux vocalinux.com VocaHQ/vocalinux ✅ Available now (v0.16.0)
🍎 macOS VocaMac vocamac.com VocaHQ/vocamac 🚀 Beta (v0.9.0)
🪟 Windows VocaWin vocawin.com VocaHQ/vocawin 🚀 Unsigned beta (v0.1.0-beta.1)
📱 Phone VocaPhone vocaphone.vocahq.com VocaHQ/vocaphone 🚀 Android beta / iOS TestFlight
🖧 Gateway VocaGateway vocagateway.vocahq.com VocaHQ/vocagateway 🧪 Early · optional · not on-device

VocaWin is unsigned. SmartScreen may warn about an unknown publisher. It is not a Microsoft Store ship.

Each platform uses native technologies. The shared bar is on-device first; VocaGateway is optional self-hosted compute and is not on-device.

Talk to us: Discord · X @vocahq · hello@vocahq.com

🤝 Contributing

We welcome contributions! Whether it's bug reports, feature requests, or code contributions, please check out our Contributing Guide.

Contributors

Thanks to everyone who has contributed to Vocalinux! 🙌

⭐ Support

If you find Vocalinux useful, please consider:

  • ⭐ Starring this repository
  • 🐛 Reporting bugs you encounter
  • 📖 Improving documentation
  • 🔀 Contributing code

📜 License

This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0), aligning with the other VocaHQ distribution projects (VocaMac, VocaPhone, VocaGateway).

You may use, study, modify, and redistribute the software under AGPL-3.0. If you run a modified version as a network service, AGPL also requires that you make the corresponding source available.

Star Chart

Star History Chart


Made with ❤️ for the Linux community

S
Description
Free, offline voice dictation for Void Linux and niri. Vulkan GPU acceleration, signed xbps repository.
Readme AGPL-3.0
35 MiB
v0.19.1
Latest
2026-11-06 21:18:19 +00:00
Languages
Python 84.5%
TypeScript 8.6%
Shell 5.6%
CSS 0.6%
Just 0.2%
Other 0.4%