Voice typing that never leaves your machine.
Hold a key, speak, release. The text lands wherever your cursor already is — transcribed by NVIDIA Parakeet on your own GPU. No account, no upload, nothing to subscribe to.
Every number here came off a stopwatch.
Eleven seconds of speech, warm median of five runs, on two RTX 3080 Ti. The clock is the engine's own monotonic origin and the interval is release-to-text — the gap you actually feel.
Four steps, and only one of them is machine learning.
The hard part of local dictation is not transcription — it is getting the words into the application you are actually using.
Trigger
evdev reads the key straight from the kernel, so it works in any session and reports press and release separately.
Capture
The microphone never stops. A rolling pre-roll means the first syllable survives talking before the key is fully down.
Transcribe
NVIDIA Parakeet TDT through ONNX Runtime, punctuating and capitalising on its own. Re-run while you speak for live text.
Inject
A /dev/uinput virtual keyboard the compositor cannot
tell from real hardware. No portal, no clipboard, no cooperation needed.
Push-to-talk, or hands-free
Hold to dictate. Double-tap to lock it on and speak freely; press again to stop. A stray tap emits nothing.
Your words, your vocabulary
A custom dictionary fixes names and jargon, and spoken commands — “new paragraph”, “scratch that” — do what they say.
Live text as you speak
The overlay shows words appearing mid-sentence, produced by the very model that will type them, so what you watch is what you get.
Where the milliseconds actually went.
int8 is a CPU optimisation. On the CUDA provider most quantised operators have no kernel, so the graph is copied back and forth across the bus and arrives exactly where it started — Murmur picks the right weights for your hardware by itself.
| Weights | Device | Warm median | Realtime factor |
|---|---|---|---|
| int8 | CPU | 477 ms | 23× |
| int8 | CUDA | 460 ms | 24× |
| fp32 | CPU | 464 ms | 24× |
| fp32 | CUDA | 36 ms | 307× |
Three things that changed the design.
Each of these was discovered by measuring something that was supposed to work.
GNOME cannot paste
Mutter exposes neither ext-data-control nor wlr-data-control,
so a background process cannot set the clipboard at all. The paste trick most
dictation tools rely on simply does not work here — Murmur types through the kernel
instead.
A device you must verify
ORT logs a failed GPU registration and quietly continues on the CPU, so a build can report success while running at a fraction of the speed. Murmur watches that log and reports the device it actually got.
The tail you cannot flush
Streaming gives a flat 14 ms tail, but never emits its final partial chunk — up to 560 ms of speech. Dictation ends exactly where that risk peaks, so live text comes from the batch model instead.
Standing on other people's shoulders.
Names and logos belong to their owners and appear here to say what Murmur is built with — not to suggest any of them endorse it.
The hard part isn't the model.
Speech recognition is solved and fast. Getting the words into the window you are looking at is where Linux fights you — GNOME cannot paste, evdev cannot swallow a single key, and an overlay that takes focus types into itself. Read the notes →
Two packages, three commands.
Each package carries both binaries, a desktop entry, the icon, and the udev rule that
makes /dev/uinput reachable.
# read access to your keyboard, so Murmur knows when the key is held $ sudo usermod -aG input $USER # then log out and back in # the speech model — 640 MB, or 2.5 GB for full precision on a GPU $ murmur models pull # check this machine can actually run it $ murmur doctor # ✓ uinput /dev/uinput is writable # ✓ trigger RIGHTCTRL declared by 3 device(s) # ✓ model parakeet-tdt-0.6b-v3-fp32 [Fp32] ← selected # then either $ murmur hud # the overlay $ murmur listen # the terminal
The group membership is a deliberate step, not something the package does for you.
Read access to /dev/input/event* is the ability to read every keystroke on
the machine; Murmur needs it to know when the trigger key is held, and no package should
grant that quietly on your behalf.