Private local STT on your Mac. Speech never leaves the machine. No cloud. No $20/month subscription.
- Option+Space — speak, text pastes at the cursor
- $0/month — not SuperWhisper or cloud dictation
- Native menu bar app + one local Whisper process
- Same API for agents — OpenAI-compatible on loopback
curl -fsS http://127.0.0.1:8765/healthz
curl -fsS -F file=@sample.wav http://127.0.0.1:8765/v1/audio/transcriptions
curl -fsS -F file=@sample.wav -F response_format=verbose_json \
http://127.0.0.1:8765/v1/audio/transcriptionsDefault language is Russian (mlx_whisper.language: ru).
Apple Silicon Mac, macOS 13+, uv.
git clone https://github.com/FUYOH666/VoiceToText.git
cd VoiceToText
uv sync
macos/scripts/build.sh
uv run python src/vtt2/main.py --installThat starts two LaunchAgents: ai.vtt2.stt (model + HTTP on 127.0.0.1:8765) and ai.vtt2 (Swift VoiceToText.app).
Grant Microphone, Accessibility, and Input Monitoring to VoiceToText — not Terminal, not python.
After an ad-hoc rebuild, macOS treats the binary as a new app: remove the old VoiceToText row in Privacy, add macos/dist/VoiceToText.app again, turn the toggles on.
uv run python src/vtt2/main.py --status
curl -fsS http://127.0.0.1:8765/healthzOpen source — run it yourself.
Or I can deploy, customize, and integrate it for your team in 2 weeks.
Free consultation: private@scanovich.ai · Telegram @ScanovichAI
- Option+Space starts recording
- Speak
- Option+Space stops
- The menu bar POSTs audio to local STT and pastes the text
The orange microphone pill is macOS (privacy). The waveform is VoiceToText.
Agents use the same POST /v1/audio/transcriptions — docs/STT_API.md. For a full transcript with timecodes (up to ~10 minutes), send response_format=verbose_json.
Default profile loads Whisper on demand and unloads after 15 minutes idle. Always-on: config.resident.yaml.
stt_server:
host: "127.0.0.1"
port: 8765
engine: mlx_whisper
preload_on_start: false
idle_unload_seconds: 900
transcription:
engine: local_stt
mlx_whisper:
model_name: "mlx-community/whisper-large-v3-mlx"
language: "ru"8 GB RAM: use whisper-medium-mlx. Optional remote GPU ASR via Tailscale lives under transcription.engine: remote_asr (keep the host in gitignored .env.vtt2).
Paste does nothing: Privacy → Accessibility and Input Monitoring → VoiceToText. After rebuild, delete the stale row and add the current .app. Text is also on the clipboard (Cmd+V). Menu: «Разрешения…».
STT slow / readyz 503: idle-unload. healthz is enough; the next POST loads the model. Always-on: cp config.resident.yaml config.yaml && uv run python src/vtt2/main.py --install.
After a git pull of STT: restart the model process so agents see the new contract — launchctl kickstart -k gui/$(id -u)/ai.vtt2.stt. Menubar can stay running.
Two menu bar icons: uv run python src/vtt2/main.py --install kills leftover UI (not --serve-stt).
Logs: ~/Library/Logs/vtt2/ (voicetotext.log, stt.stdout.log).
uv run pytest
macos/scripts/test.shNotarized .app needs Apple Developer + macos/Signing.xcconfig (not in git) and macos/scripts/release.sh. No signed public zip is attached until a Developer ID exists.
MIT. Built with MLX.
