Hold a key. Speak. Text appears — and your audio never leaves your machine.
▶ Try it in your browser — works on your phone too.
MicText is an embeddable STT library for the web plus reference push-to-talk dictation clients for macOS and Windows, all running Whisper locally. An optional self-hosted fallback server covers devices too slow to run the model.
| Component | What it is |
|---|---|
web/ |
Browser library: Whisper in a Web Worker (WebGPU → WASM). Headless createTranscriber() core + <mictext-mic> element. npm i mictext |
mac/ |
macOS dictation client: hold right-⌥, speak, release — text typed at the cursor (Hammerspoon + ffmpeg + whisper.cpp) |
win/ |
Windows dictation client: hold Right Ctrl (AutoHotkey v2 + ffmpeg + whisper.cpp) |
server/ |
Optional self-hosted fallback (FastAPI + faster-whisper) for the web library's explicit slowDevice: 'server' opt-in |
All three clients share the same behaviour, tuned per platform:
- Warming vs. recording. Opening the capture device takes up to a second on the first press of a session. Each client shows that as a distinct warming state — a dim pill and a
🎙…icon on macOS, a grey pill and "warming up" tooltip on Windows, awarmingattribute on<mictext-mic>— and only switches to the recording look once audio is genuinely being captured. Wait for it and no first words are lost. - Silence is silence. A hold that carried no speech types nothing and shows nothing. Whisper's silence hallucinations (
[BLANK_AUDIO],Thank you.) are dropped too. - It learns your words. Correct a transcript (⌥⇧F on macOS, Alt+Shift+F on Windows,
mic.learn()on the web) and the pair is remembered in~/.mictext/terms.json— fed back to Whisper as decoding context and applied as a replacement. Local file, local only; the desktop clients share one file format.
With the default configuration, no code path in this repo POSTs your audio
anywhere. The web library only GETs model files (verified end-to-end with
full network logging — see web/README.md); the desktop
clients work with Wi-Fi off. The single exception is the web library's
slowDevice: 'server' opt-in, which sends audio to a fallback URL you
configure — typically your own server/ deployment.
Browser — npm i mictext, then:
import { createTranscriber } from 'mictext'
const t = createTranscriber()
const { text } = await t.transcribeBlob(audioBlob)macOS — one line (then hold right-⌥ and speak):
curl -fsSL https://raw.githubusercontent.com/dieterstemmet/mictext/master/mac/install.sh | bashWindows — one line in PowerShell (then hold Right Ctrl and speak):
irm https://raw.githubusercontent.com/dieterstemmet/mictext/master/win/install.ps1 | iexConfigure mic, hotkey, and model from the tray Settings... menu, or win\config.ps1 from a clone.
(mac/README.md / win/README.md)
Mobile browsers don't allow system-wide dictation, so there's no
push-to-talk client for iOS/Android — but the web library runs fine on
phones (the default whisper-tiny.en model exists exactly for mobile
WebKit's memory limits):
- Use the hosted demo: open it on your phone, hold the mic, speak, copy the text anywhere. "Add to Home Screen" gives it an app icon.
- Embed it in any web app with
<mictext-mic>— seeweb/. - System-wide mobile dictation would need a native keyboard app (iOS keyboard extension / Android IME) — a possible future direction.
The durable interface is the headless transcriber
(createTranscriber().transcribeBlob(blob) on the web; whisper-cli behind
a hotkey on desktop). Dictation — "type what I said at the cursor" — is just
the first frontend. The same ears can feed a voice assistant: that's the
direction this project grows in, and why no client logic lives in the core.
MIT