Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

micstt

Live local streaming speech-to-text using faster-whisper (CTranslate2 port of OpenAI Whisper) running entirely on-device — no audio ever leaves your machine.

While you speak, micstt retranscribes overlapping snapshots with fast greedy decoding and shows a replaceable partial hypothesis. After VAD detects the end of the utterance, it runs a higher-quality final pass and commits the result. Audio and inference work queues are bounded so a slow machine cannot accumulate unlimited latency or memory.

Two ways to run it:

  • micstt — CLI, prints each transcribed utterance to stdout
  • micstt-gui — cross-platform (macOS/Windows) system tray app with a transcript window, a mic selector, and a live input level meter

Setup

macOS

brew install portaudio
pip install -e .

Windows

No system package needed — the sounddevice wheel bundles PortAudio.

pip install -e .

ffmpeg is not required either way — audio is captured directly as raw PCM and never goes through file/codec decoding.

GUI (micstt-gui)

micstt-gui

Launches a system tray icon (yellow while loading the model, green while listening, red on error, gray once stopped). Click it — or right-click → "Show Transcript" — to open the transcript window, which has:

  • Mic — pick the input device (right-click the tray icon → "Refresh Devices" if you plug in a new mic/headset after launch)
  • a live dB level bar so you can see audio is actually reaching the mic before waiting on a transcription

The GUI always uses the small Whisper model and Korean (ko) — there is no model or language selector. The model downloads automatically from Hugging Face on first use.

Quit from the tray menu.

Prebuilt desktop apps

A GitHub Actions workflow (.github/workflows/build.yml) builds standalone micstt-gui apps via PyInstaller for both Windows (windows-latest, one-file .exe) and macOS (macos-latest, ad-hoc-signed .app bundle) on every push to main, or on demand with gh workflow run build.yml. It then publishes both to a rolling latest GitHub Release — the easiest way to grab a build is the Releases page rather than digging through Actions artifacts.

Both builds are unsigned/ad-hoc-signed, so:

  • Windows: SmartScreen will warn on first run — "More info" → "Run anyway".
  • macOS: unzip and move micstt-gui.app to Applications. On current macOS, right-click → Open no longer offers a Gatekeeper bypass for ad-hoc-signed apps — you'll just get a "can't be opened" dialog with no override option. Instead, strip the quarantine attribute from Terminal, then launch normally:
    xattr -cr /Applications/micstt-gui.app
    
    (Alternative: System Settings → Privacy & Security → scroll down to the blocked-app notice → "Open Anyway", which appears after the first blocked launch attempt.)

CLI (micstt)

micstt --list-devices        # find your mic's device index/name
micstt                       # start listening (default model: small, language: ko)
micstt --model small --lang en
micstt --audio-file data/sample.wav --lang ko  # replay WAV through the realtime pipeline
micstt --audio-file data/sample.wav --play-audio  # ...and also hear it played back through speakers

Partial hypotheses are displayed on stderr while you speak. Pause briefly and each finalized utterance is printed as one line to stdout. This keeps stdout clean for piping, e.g. micstt | tee transcript.txt.

Ctrl+C to stop.

Flags

Flag Default Description
--model small tiny/base/small/medium/large — speed vs. accuracy tradeoff
--lang ko Pin a language code (e.g. en, ko) to skip detection overhead
--mic-device system default Device index or name substring
--audio-file none Replay a 16 kHz mono 16-bit PCM WAV in realtime instead of using a mic
--play-audio off Also play --audio-file through speakers while streaming it
--silence-duration 800 ms of silence that ends an utterance
--vad-aggressiveness 2 0-3, VAD sensitivity
--partial-interval 1.0 Seconds between overlapping live hypotheses
--debug-audio-dir none Dump each finalized utterance's audio as a WAV file into this directory, for later replay via --audio-file when a misrecognition needs investigating

Handling jargon/domain vocabulary

Whisper sometimes mishears domain-specific jargon, product names, or people's names it hasn't seen before. Both the CLI and GUI always bias recognition using two hardcoded constants in src/micstt/vocab.py — hardcoded rather than a flag or config file since this rarely changes:

  • MEETING_PROMPT — free-text company/meeting background, e.g. "올라핀테크는 ... 대안 금융 핀테크 스타트업입니다."
  • JARGON_WORDS — a list of jargon terms/names, e.g. ["올라선정산", "레븐", "리스크 스코어링"]

To update the vocabulary, edit vocab.py directly and commit — everyone gets the update on their next git pull (including the next prebuilt desktop app release, since it's just source code). If both constants are empty, no prompt is used.

It's a soft bias, not a guarantee: very unusual terms may still get missed, especially at smaller --model sizes. This has no relation to condition_on_previous_text (kept off deliberately, see transcriber.py) — the prompt is a fixed hint applied identically to every independent utterance, not accumulated transcript history, so it doesn't reintroduce the repetition-loop risk that setting was meant to avoid.

First run

The model downloads once from Hugging Face (~150MB for base, more for larger variants) and is cached under ~/.cache/huggingface/hub/ (%USERPROFILE%\.cache\huggingface\hub on Windows). Subsequent runs are fully offline.

Microphone permission (macOS)

The first time you run micstt/micstt-gui from a given terminal app, macOS will prompt for microphone access — this dialog only appears in an interactive session, not when launched from a non-interactive/automated context. If it hangs with no prompt, check System Settings > Privacy & Security > Microphone, enable access for your terminal app (or the micstt-gui.app itself), then re-run.

Also check System Settings > Sound > Input — if the input volume is turned down, audio will look like it's capturing (no errors) but transcription will silently fail because the mic level is too quiet. The GUI's level bar makes this obvious; the CLI does not currently show levels.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages