I started ThunderTalk because every voice-to-text app I tried fell into one of two camps: cloud-only (great accuracy, but my microphone audio is now a third party's training set), or "local" but quietly phoning home for the model. I wanted something I could read the source of, run offline on a plane, and trust with a confidential meeting.
Why local ASR is finally tractable
Two years ago, running a real ASR model locally on a laptop meant either Whisper-tiny (fast, mediocre) or Whisper-large (good, but a 10-second clip took 8 seconds of CPU). Apple Silicon and the MLX framework changed the arithmetic:
- Qwen3-ASR-0.6B (MLX fp16) runs at RTF ≈ 0.05 on an M3 — 20× faster than the audio you spoke.
- The model is 1.2 GB. It fits in the cache of any modern Mac, and the first-token latency after warm-up is ~200 ms.
- No GPU compromise. MLX targets the unified memory architecture directly, so I'm not fighting CUDA wrappers or Metal shims.
The practical consequence: a hotkey-triggered "press to dictate" workflow that feels indistinguishable from a cloud service, except it works on a plane and it's free.
What I underestimated
The model wasn't the hard part. The hard parts were:
- macOS permissions theater. Microphone, Accessibility, and Input Monitoring are three separate consent flows, and the app gets re-quarantined every time you move it between folders.
- Hotkey global capture. PySide6 doesn't expose system-wide hotkeys; I ended up writing a thin Objective-C bridge over
CGEventTap. - Hotwords. Out-of-the-box ASR mangles every product name and acronym in your team's vocabulary. The Qwen3 hotwords interface is well-designed but undocumented; I wrote an integration test suite just to characterize what it would and wouldn't accept.
Update, September 2026: ThunderTalk 1.5
Since the 1.0 post, ThunderTalk has grown from a dictation tool into a small local speech workbench. The headline is Studio, which replaces the old Lab page:
- Transcribe. Drop in an audio or video file and get a timestamped transcript. For meetings, Multiple speakers mode uses MOSS-Transcribe-Diarize to label every turn, for recordings up to about 90 minutes in one pass. Export to TXT, Markdown, SRT, VTT or JSON. Decoding uses what's built into macOS, so no ffmpeg.
- Speak. Text to speech with three local engines: VoxCPM2 (48 kHz, voice cloning), IndexTTS-2.5 (very faithful cloning in five languages) and Kokoro (82M, about 4× real time on the CPU).
- My voices. Record 5 to 15 seconds of your own voice and it can read anything you type. The reference never leaves
~/.thundertalk/voices.
Dictation got better too:
- More models. Qwen3-ASR 0.6B and 1.7B, SenseVoice-Small, NVIDIA Parakeet-TDT and MOSS-Transcribe-Diarize. The app reads your hardware and recommends one. Parakeet-TDT runs at RTF 0.019 on an M3 Max, about 50× faster than real time.
- Small things that matter. Spoken numbers become digits in English and Chinese, translation into 100+ languages with SeamlessM4T v2, a searchable history, and an in-app updater.
Two practical notes. ThunderTalk now needs an Apple Silicon Mac on macOS 15 or later; the early README said macOS 12 and Intel, which was wrong. And you can install it with Homebrew:
brew install --cask realallensong/tap/thundertalk
The privacy promise hasn't changed: no account, no subscription, and your audio never leaves your Mac.
If you try it, let me know what breaks. The repo's at realAllenSong/ThunderTalk.