# Building cross-distro offline voice dictation for Linux (and why it took more than a model)

> Source: <https://dev.to/jatinkrmalik/building-cross-distro-offline-voice-dictation-for-linux-and-why-it-took-more-than-a-model-1ie8>
> Published: 2026-07-15 06:14:56+00:00

Linux is great at a lot of things. Voice typing has not been one of them.

On Windows and macOS you get system dictation that works in basically any app. On Linux you get cloud services, research scripts, and CLI tools that only make sense if you already know how speech stacks fit together. I wanted something closer to: press a shortcut, talk, text appears. Prefer offline. Free. Not tied to one distro.

That is [Vocalinux](https://github.com/jatinkrmalik/vocalinux). GPLv3 tray app. System-wide speech-to-text on X11 and Wayland. Default engine is whisper.cpp running on your machine. You can also pick OpenAI Whisper, VOSK, or a **Remote API** engine that talks to your own HTTP STT server (OpenAI-compatible or whisper.cpp's server). Core path needs no account and does not send audio to a random SaaS.

This is the story and the technical path, not a feature dump.

I kept tripping over the same three constraints:

Pieces of the puzzle already existed. whisper.cpp made local Whisper models practical. VOSK was light enough for older boxes. Projects like nerd-dictation showed people wanted FOSS options. What I did not find was a multi-engine tray app that treated Wayland as a real problem, stayed offline by default, and still let power users point at a home-lab GPU when they wanted to.

So I started building one.

Numbers as of mid-2026. The project is still beta on purpose.

| When | What |
|---|---|
Early 2025 |
Design and early work around offline Linux dictation |
April 2025 |
Public GitHub repo:
|

`v0.2.0-alpha`

). Installer and engine choices start to harden`v0.5.0-beta`

and friends). Site at `v0.14.0-beta`

: custom modifier+key hotkeys, FunASR/SenseVoice over remote OpenAI-compatible APIs, more Wayland fixes, smarter whisper.cpp thread defaults on hybrid CPUsStill beta because desktop Linux dictation has a long tail of compositor and input-method bugs.

In practice:

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

First install is usually a couple of minutes with the default tiny whisper.cpp model. Bigger models cost RAM and latency for accuracy.

Stack: Python 3.9+, GTK 3 (PyGObject), the speech backends above, then a lot of stubborn work on audio capture and text injection.

Local models are the default story. Remote is the escape hatch when your laptop is weak, you already run a Whisper box on the LAN, or you want one GPU server shared by a few machines.

How it works when **Remote API** is selected:

Two wire formats out of the box (docs: [HTTP remote transcription](https://github.com/jatinkrmalik/vocalinux/blob/main/docs/HTTP_REMOTE.md)):

| Format | Endpoint idea | Examples |
|---|---|---|
OpenAI-compatible |
`POST /v1/audio/transcriptions` |
Speaches, LocalAI, FunASR/SenseVoice servers, or a self-hosted stack that mimics OpenAI's audio API |
whisper.cpp server |
`POST /inference` |
The HTTP server binary from
|

You are not locked into OpenAI's cloud. Point the base URL at `http://your-lab:8000`

(or whatever you run). As of `v0.14.0-beta`

, OpenAI-compatible remote mode also understands FunASR/SenseVoice-style model names (e.g. `sensevoice`

) and cleans SenseVoice metadata labels before injection.

Same self-hosted server can back other clients on the network (phones, other desktops) if they speak the same API. Audio goes to *your* box, not a random vendor, unless you deliberately configure a public endpoint.

Remote does **not** replace offline mode. It is for people who want the tray UX on a thin client and the heavy ASR somewhere else they trust.

Getting a transcript string is easy. Users live in browsers, IDEs, chat, LibreOffice, terminals. The product is "text landed where the caret is," not "something printed on stdout."

That means:

A lot of recent releases are those bugs, not new models. That is the right bias for desktop software.

On X11 you could fake more with older tools. Wayland is stricter and more compositor-specific. Vocalinux spends time on injection paths for modern GNOME and Plasma, then spends more time fixing regressions when detection or engines move.

If you only test one DE, you ship "works on my machine" and break on the next Reddit thread.

There is no single STT stack that wins for everyone:

| Engine | Role |
|---|---|
whisper.cpp |
Default local path. Good speed/quality tradeoff, Vulkan-friendly, avoids PyTorch for many users |
OpenAI Whisper |
Local PyTorch path; NVIDIA-oriented GPU story |
VOSK |
Lighter local footprint on older hardware |
Remote API |
Offload ASR to whisper.cpp server or any OpenAI-compatible STT (Speaches, LocalAI, FunASR/SenseVoice, etc.) while VAD stays local |

The installer recommends something sane from RAM, GPU, and Vulkan. Settings keep model selection per engine so switching does not wipe preferences. Remote is configured with server URL, endpoint style, and model name when the server needs one.

Offline means:

Air-gapped and flaky-network laptops care about the first path. Homelab people care about the second. Both are valid; the default still does not require a network.

People notice tray icons, short audio cues, whether push-to-talk matches muscle memory, whether a pause between phrases inserts a space instead of gluing words, and whether hybrid CPUs cook because the STT library grabbed every core.

v0.14.0-beta is full of that kind of work: hotkeys, hybrid-CPU thread defaults, Wayland/IBus reliability, remote SenseVoice cleanup. Unsexy. Necessary.

Linux desktop users who want dictation without defaulting to cloud STT. People reducing keyboard load (RSI, accessibility, long writing sessions). Devs who live in terminals and editors but still want system-wide capture. Privacy-minded folks who want GPLv3 code they can read. Homelab users who already run Whisper (or FunASR) on a box and want a proper Linux client in front of it.

It is not a commercial Dragon replacement with a sales team. It is a community desktop app that should be good enough to leave running every morning.

I would not drop the offline default, the multi-engine design (including remote), or Wayland injection as core work.

I would start earlier on packaging (Flatpak, AUR, and friends) as a real channel, not only the install script. More automated DE matrix testing for injection. Clearer "what works where" docs from day one. Remote setup could use more opinionated presets for common servers so people do not have to read endpoint docs on a bad day.

Still open: broader packages, a better docs hub, and the endless DE/compositor bugs that only show up when real keyboards and layouts hit the wild.

If you try it on a weird Wayland setup, open an issue with distro, DE, and whether injection or recognition failed. Same for remote: say which server software and endpoint style you used. Those reports are how the history above got written.

I am still shipping betas on purpose. Desktop dictation on Linux only gets good if people use it in the wild and we keep fixing what they hit.

*Disclaimer: I am the maintainer of Vocalinux. Feedback welcome on GitHub issues/discussions.*
