Local speech-to-text CLI powered by NVIDIA's Parakeet TDT 0.6B v3 model. Runs entirely on-device via ONNX Runtime — no cloud APIs, no network required after model download.
- High accuracy — NVIDIA Parakeet TDT 0.6B v3 with punctuation and capitalization
- 25 languages — English, Spanish, French, German, Italian, Portuguese, Russian, Polish, Ukrainian, Czech, Slovak, Dutch, Swedish, Danish, Finnish, and more
- Fully local — all inference runs on-device; audio never leaves your machine
- Fast — ~59x realtime on Apple Silicon CPU with FP16 quantization
- Small footprint — 1.2 GB FP16 model (or 652 MB INT8)
- File transcription — transcribe WAV files with text or JSON output
- Live microphone — stream transcription from any audio input device with voice activity detection (Silero VAD v5)
- Daemon mode — background service controllable via Unix socket or signals, designed for hotkey-triggered dictation (Hammerspoon, skhd, Karabiner)
- Clipboard output — optional
--clipboardflag pastes transcription directly - CoreML support — experimental CoreML acceleration via
--coremlflag
- macOS on Apple Silicon (M1/M2/M3/M4)
- Rust 1.85+ (edition 2024)
- ~1.3 GB disk space for FP16 model weights (or ~670 MB for INT8)
Linux/Intel Mac may work with CPU-only inference but are untested.
brew install lucataco/tap/parakeet-cligit clone https://github.com/lucataco/parakeet-cli.git
cd parakeet-cli
cargo build --release --bin parakeetThe binary is at target/release/parakeet. Optionally copy it to your PATH:
cp target/release/parakeet /usr/local/bin/parakeet# 1. Download model weights (~670 MB INT8 by default)
parakeet download
# 2. Transcribe a file
parakeet transcribe recording.wav
# 3. Live transcription from microphone
parakeet listenDownload model weights from HuggingFace. Files are cached and skipped if already present.
parakeet download [OPTIONS]
Options:
--model-dir <PATH> Directory to store model files
[default: ~/Library/Application Support/parakeet/models/parakeet-tdt-0.6b-v3]
--fp16 Download FP16 quantized model (1.2 GB) instead of the default INT8 weights.
-v, --verbose Enable verbose output
Transcribe a WAV audio file (any sample rate — automatically resampled to 16kHz).
parakeet transcribe <FILE> [OPTIONS]
Options:
--model-dir <PATH> Directory containing model files
--format <FORMAT> Output format: text, json [default: text]
--coreml Enable CoreML acceleration (experimental)
-v, --verbose Enable verbose output (model details, tensor shapes, timing stats)
Example with JSON output:
parakeet transcribe meeting.wav --format jsonStream transcription from the microphone in real time. Uses Silero VAD v5 to detect speech boundaries — when you stop talking, the utterance is transcribed and printed.
Press Ctrl-C to stop.
parakeet listen [OPTIONS]
Options:
--device <NAME> Audio input device (substring match; use 'devices' to list)
--model-dir <PATH> Directory containing model files
--vad-threshold <F32> VAD speech probability threshold, 0.0-1.0 [default: 0.5]
--silence-ms <MS> Silence duration in ms to end an utterance [default: 1500]
--clipboard Copy each transcription to clipboard (via pbcopy)
--debug Print debug info: audio levels, VAD probabilities, state transitions
--coreml Enable CoreML acceleration (experimental)
-v, --verbose Enable verbose output (model details, tensor shapes, timing stats)
Example with a specific microphone and tighter VAD:
parakeet listen --device "MacBook Pro" --vad-threshold 0.6 --silence-ms 1000Run as a background daemon controllable via Unix socket or Unix signals. Designed for hotkey-triggered dictation workflows.
parakeet serve [OPTIONS]
Options:
--socket <PATH> Unix socket path [default: ~/Library/Application Support/parakeet/run/daemon.sock]
--pid-file <PATH> PID file path [default: ~/Library/Application Support/parakeet/run/daemon.pid]
--device <NAME> Audio input device
--model-dir <PATH> Directory containing model files
--clipboard Copy transcription to clipboard (via pbcopy)
--coreml Enable CoreML acceleration (experimental)
-v, --verbose Enable verbose output (model details, tensor shapes, timing stats)
See Daemon Mode below for control commands and integration examples.
List available audio input devices.
parakeet devicesAudio input devices:
MacBook Pro Microphone (default): 1ch, 48000Hz, F32
External USB Mic: 2ch, 44100Hz, I16
Two quantization levels are available, both based on Parakeet TDT 0.6B v3:
| Variant | Encoder | Decoder | Total | Speed | Download |
|---|---|---|---|---|---|
| INT8 (default) | 652 MB | 18 MB | ~670 MB | ~50x realtime | parakeet download |
| FP16 | 1.2 GB | 35 MB | ~1.3 GB | ~59x realtime | parakeet download --fp16 |
The model loader auto-detects which variant is present and prefers FP16 > INT8 > FP32 (legacy). FP32 legacy models may use external data files (.onnx.data), which are automatically preloaded.
The serve command starts a background process that loads the model once and waits for commands. This avoids the ~1 second model load time on each invocation, making it ideal for hotkey-triggered dictation.
By default the daemon uses a private per-user runtime directory. For shell examples below:
PARAKEET_SOCKET="$HOME/Library/Application Support/parakeet/run/daemon.sock"
PARAKEET_PID="$HOME/Library/Application Support/parakeet/run/daemon.pid"Send commands to $PARAKEET_SOCKET as plain text or JSON:
# Toggle recording on/off
echo "toggle" | nc -U "$PARAKEET_SOCKET"
# Start recording
echo "start" | nc -U "$PARAKEET_SOCKET"
# Stop recording and transcribe
echo "stop" | nc -U "$PARAKEET_SOCKET"
# Check daemon status
echo "status" | nc -U "$PARAKEET_SOCKET"
# Shut down the daemon
echo "shutdown" | nc -U "$PARAKEET_SOCKET"JSON format is also accepted:
echo '{"command":"toggle"}' | nc -U "$PARAKEET_SOCKET"| Signal | Action |
|---|---|
SIGUSR1 |
Toggle recording on/off |
SIGUSR2 |
Stop recording & transcribe |
SIGINT |
Shut down daemon |
# Toggle via signal (using PID file)
kill -USR1 $(cat "$PARAKEET_PID")
# Stop recording
kill -USR2 $(cat "$PARAKEET_PID")Bind a hotkey to toggle dictation:
-- ~/.hammerspoon/init.lua
hs.hotkey.bind({"cmd", "shift"}, "D", function()
hs.execute("echo toggle | nc -U \"$HOME/Library/Application Support/parakeet/run/daemon.sock\"", true)
end)# ~/.skhdrc
cmd + shift - d : echo "toggle" | nc -U "$HOME/Library/Application Support/parakeet/run/daemon.sock"
Use a complex modification to map a key to:
echo "toggle" | nc -U "$HOME/Library/Application Support/parakeet/run/daemon.sock"src/
├── main.rs # Entry point, command dispatch
├── cli.rs # Clap CLI definitions
├── download.rs # HuggingFace model download (multi-repo)
├── listen.rs # Live mic → VAD → transcribe pipeline
├── serve.rs # Daemon mode (socket + signal control)
├── audio/
│ ├── mel.rs # 128-bin log-mel spectrogram (FFT, Hann window, mel filterbank)
│ ├── resample.rs # WAV loading, stereo→mono, linear interpolation resampling
│ ├── capture.rs # Mic capture via cpal (multi-format, multi-channel)
│ └── buffer.rs # Growable audio buffer for utterance accumulation
├── model/
│ ├── encoder.rs # ONNX encoder session (CoreML + CPU, external data preloading)
│ ├── decoder.rs # TDT greedy decoder with LSTM state management
│ └── tokenizer.rs # SentencePiece vocab, token ID → text
└── vad/
└── silero.rs # Silero VAD v5 ONNX, VadSegmenter state machine
File transcription:
WAV file → resample to 16kHz mono → 128-bin log-mel spectrogram
→ Encoder (ONNX) → TDT Decoder (greedy, autoregressive) → Tokenizer → text
Live streaming:
Microphone → mono f32 chunks → resample to 16kHz
→ Silero VAD (32ms chunks) → detect speech/silence boundaries
→ accumulate utterance → transcribe on speech end → output
| Component | File (FP16) | Size |
|---|---|---|
| Encoder | encoder-model.fp16.onnx |
1.2 GB |
| Decoder | decoder_joint-model.fp16.onnx |
35 MB |
| Tokenizer | vocab.txt (8193 tokens, 25 languages) |
92 KB |
| VAD | silero_vad.onnx (auto-downloaded) |
2.3 MB |
- Encoder input: 128-bin mel features, 16kHz audio, 25ms window, 10ms hop
- Decoder: TDT (Token-and-Duration Transducer) with greedy search and duration-based time stepping
- Tokenizer: SentencePiece unigram, 8193 tokens (v3 multilingual) including blank
Run the unit tests (no model files required):
cargo testThe project includes a comprehensive Criterion.rs benchmark suite covering every stage of the STT pipeline.
Run all benchmarks:
cargo benchRun a specific benchmark suite:
cargo bench -- mel_spectrogram # Mel spectrogram computation (CPU-only)
cargo bench -- resample # Audio resampling & stereo-to-mono (CPU-only)
cargo bench -- vad # Silero VAD inference & segmenter
cargo bench -- encoder # ONNX encoder inference
cargo bench -- decoder # TDT greedy decoder loop
cargo bench -- end_to_end # Full audio-to-text pipeline
cargo bench -- memory # Memory allocation trackingBenchmarks that require model files (
encoder,decoder,end_to_end,memory) will skip gracefully with a message if the model hasn't been downloaded. Runparakeet downloadfirst to enable them. VAD benchmarks requiresilero_vad.onnx, which is auto-downloaded on the firstparakeet listenrun.
What's measured:
| Benchmark Suite | What It Measures | Model Required |
|---|---|---|
mel_spectrogram |
FFT + filterbank throughput across 1s-60s audio | No |
resampling |
One-shot vs streaming resampling, stereo-to-mono | No |
vad |
Per-chunk VAD latency, streaming throughput, segmenter state machine | VAD model |
encoder |
Encoder inference time and realtime factor (1s-30s) | Yes |
decoder |
Decoder step latency and total decode time | Yes |
end_to_end |
Full pipeline RTF, batch throughput (10x5s sequential) | Yes |
memory |
Allocation sizes per stage (mel, buffer, encoder, full pipeline) | Partial |
HTML reports are generated in target/criterion/ for regression tracking across runs.
GitHub Actions runs the main CI checks on macOS via .github/workflows/ci.yml:
cargo fmt --checkcargo clippy --all-targets --all-features -- -D warningscargo testcargo build --release --bin parakeet
Use scripts/release.sh to keep the crate version, release notes, git tag, and Homebrew tap update flow in sync.
# 1. Bump the crate version and scaffold release notes
scripts/release.sh prepare 0.1.4
# 2. Review docs/releases/v0.1.4.md, then commit and push main
git add Cargo.toml Cargo.lock docs/releases/v0.1.4.md
git commit -m "release v0.1.4"
git push origin main
# 3. Tag the release from the current HEAD and push the tag
scripts/release.sh tag 0.1.4
git push origin v0.1.4
# 4. Update the tap once the tag tarball is available
scripts/release.sh update-tap 0.1.4 --tap-dir /path/to/homebrew-tapBenchmarked on Apple Silicon (M-series), CPU inference with FP16 model:
| Metric | Value |
|---|---|
| Inference speed | ~59x realtime |
| Model load time | ~1.1 seconds |
| Download size | ~1.3 GB (FP16) |
| Streaming latency | Utterance end + ~0.5s transcription |
Licensed under the Apache License, Version 2.0. See LICENSE for details.
The NVIDIA Parakeet TDT model weights are subject to NVIDIA's CC-BY-4.0 license. The Silero VAD model is licensed under MIT.