Global voice dictation on Linux needs four working parts: a way to capture microphone audio, a hotkey daemon that listens system-wide, a transcription engine, and a way to type the result into whatever window has focus. On X11 that last part is trivial. On Wayland it's the part that breaks most DIY setups, because the compositor deliberately blocks apps from injecting keystrokes into windows they don't own.
Cloud dictation tools sidestep the local input problem by running as browser extensions or by owning the whole window, but that means your audio leaves the machine every time you talk. That's a real cost: latency on every utterance, a dependency on an API being up when you need to type, and a permanent copy of your voice sitting on someone else's infrastructure. For anything you'd rather not narrate to a third-party server โ passwords, client names, unreleased code โ that's not paranoia, it's just what "cloud" means.
The alternative is doing transcription on-device and injecting the text locally. That's mechanically straightforward on X11, where any process can simulate input. Wayland's security model treats that as a vulnerability class (it's literally how X11 keyloggers work) and locks it down per-compositor. So a Linux dictation tool has to solve input injection twice.
1. Audio capture. PortAudio (or ALSA/PipeWire directly) opens the mic and streams frames to your transcription engine. You generally want voice activity detection (VAD) in front of it โ silero-vad or webrtcvad โ so you're not transcribing dead air between sentences and burning CPU on an idle mic.
2. A global hotkey daemon. You need something listening for a key combo regardless of which window has focus. On X11 this is usually a raw X grab via a library like python-xlib or a binding through evdev. On Wayland, compositors don't expose global hotkeys through the display protocol at all โ the practical answer is reading raw input events from /dev/input/event* via evdev, which is compositor-agnostic and works identically under GNOME, KDE, or Sway.
3. Transcription. This is where faster-whisper (a CTranslate2 reimplementation of Whisper) does the actual speech-to-text, entirely on-device. Model size is a real tradeoff โ base or small run fine on a CPU in near real time, medium and above want a GPU if you don't want a noticeable pause after you stop talking.
4. Typing the output. This is ydotool's job, and it's why it exists as a separate project from the older xdotool. Instead of talking to the X server, ydotool talks to a virtual input device via uinput โ it injects events at the kernel level, below the compositor, so it works identically on Wayland and X11. The catch: writing to /dev/uinput requires either root or membership in the input group, plus the ydotoold daemon running to broker requests. Add yourself with sudo usermod -aG input $USER, log out and back in, and start the daemon before your hotkey tool tries to use it.
5. A systemd user service. None of this is useful if you have to remember to launch it manually. A user unit in ~/.config/systemd/user/ with WantedBy=default.target, enabled via systemctl --user enable --now, starts your daemon on login and restarts it if it crashes โ same pattern as any other background service, just scoped to your session instead of the system.
This is the exact stack Voxtty runs: PortAudio for capture, an evdev-based hotkey daemon so Alt+D works the same on GNOME/Wayland and i3/X11, faster-whisper for on-device transcription, and ydotool for the actual typing โ packaged as a systemd user service so it's running before you've opened your first terminal. Nothing leaves the machine except, optionally, the transcript text if you opt into AI cleanup โ never the audio. Try Voxtty free if you'd rather not wire the four pieces together yourself.
Whisper models struggle with strong accents, heavy background noise, and dense technical jargon โ expect more correction on words like library or framework names than on plain prose. VAD tuned too aggressively will clip the start of sentences; tuned too loosely, it transcribes your keyboard clicks. ydotool's uinput approach means it types faster than a human but not instantaneously โ on some GTK apps rapid injected keystrokes can outrun the text field's redraw and drop characters, so a small per-key delay is often necessary. And because Wayland's hotkey path relies on raw evdev reads rather than a compositor API, it needs that same input group membership as ydotool โ one more reason to get the group permission right first, before debugging anything else.
Check whether ydotool is packaged for your distro (apt show ydotool, pacman -Ss ydotool, or check the AUR/COPR) and confirm your user is in the input group with groups $USER. Getting that permission sorted is the single step that unblocks everything else, on both X11 and Wayland.
Local-first voice dictation for Linux. Press Alt+D, speak, and your words land in whatever app has focus โ nothing leaves your machine.
Try Voxtty free โ