Russian speech-to-text terminal TUI powered by GigaAM-v3 (Hugging Face Hub, revision
e2e_rnnt).
Push-to-talk Russian speech recognition in your terminal. Records from
your microphone, transcribes with GigaAM-v3-e2e-rnnt, and shows
timestamped text in a chat-style TUI. Copies to clipboard with
Ctrl+C, saves to .txt or .md with Ctrl+S, and exits cleanly
with Ctrl+Q.
The console-script entry point is wired via pyproject.toml's
[project.scripts]; the package entry is src/ru_stt_tui/__main__.py.
The root-level main.py from the initial empty repo is not part of
this project.
- Push-to-talk: press
Spaceto start, press again to stop & transcribe - In-app device picker: lists microphones at startup, persists your choice in
config.toml - Atomic transcription: status bar shows
Transcribing 1.4swhile the model runs, then text appears in one shot - Russian text with punctuation and casing preserved (e2e_rnnt model variant)
- GPU auto-detect: PyTorch fp16 on CUDA when available; CPU fallback is plain PyTorch (no ffmpeg or ONNX runtime needed)
- Clipboard:
Ctrl+Ccopies the last segment viapyperclip - Save:
Ctrl+Sopens an in-TUI path/format picker (.txtor.md) - Worker recovery:
Ctrl+Rrestarts the ASR worker on failure - Cancellation:
Esccancels an in-flight recording or transcription - Cross-platform: Windows, macOS, Linux (Python 3.10+)
┌─ Transcript ─────────────────────────────────────────────────────┐
│ [14:23:01] Привет, мир. │
│ [14:23:18] Как дела? │
│ [14:24:02] Сегодня хорошая погода. │
└──────────────────────────────────────────────────────────────────┘
┌─ Status ─────────────────────────────────────────────────────────┐
│ READY | Space: record Ctrl+C: copy Ctrl+S: save Ctrl+Q: quit│
└──────────────────────────────────────────────────────────────────┘
- Python 3.10 or newer (tested on 3.12)
- A working microphone (PortAudio backend;
sounddeviceships its own wheels on Windows, macOS, and Linux) - ~3 GB free disk for the GigaAM-v3 model cache (
~/.cache/huggingface/) - First run downloads the model (~2.5 GB) from
ai-sage/GigaAM-v3(revisione2e_rnnt) on Hugging Face Hub
The model is loaded via
transformers.AutoModel.from_pretrained(...)and weights are stored under the standard HF cache directory — no separate~/.cache/gigaam/directory is used.
Primary (editable, for development):
pip install -e .Alternatives:
uv pip install -e .
# or
pipx install .Basic launch:
ru-stt-tuiUseful flags:
| Flag | Purpose |
|---|---|
--list-devices |
List available input devices and exit |
--device N |
Override the audio device (skips the picker) |
--setup-only |
Download the model (~2.5 GB) and exit (no TUI) |
--cpu |
Force CPU inference (skip the CUDA probe) |
--no-progress |
Print progress to stderr (no TUI progress bar) |
--timing |
Print per-transcription timing to stderr and append a JSONL line to ~/.cache/ru-stt-tui/timings.jsonl |
--config PATH |
Override the config file path |
--version |
Print version and exit |
--help |
Show help and exit |
| Key | Action |
|---|---|
Space |
Toggle push-to-talk (start/stop recording) |
Ctrl+C |
Copy the last segment to clipboard |
Ctrl+S |
Open the save dialog (path + format) |
Ctrl+R |
Restart the ASR worker (recovery) |
Esc |
Cancel in-flight recording or transcription |
Ctrl+Q |
Quit cleanly |
The app reads and writes a TOML config file at:
- Windows:
%APPDATA%\ru-stt-tui\config.toml - macOS:
~/Library/Application Support/ru-stt-tui/config.toml - Linux/other:
~/.config/ru-stt-tui/config.toml(or$XDG_CONFIG_HOME/ru-stt-tui/config.toml)
The path falls back through a three-tier chain (platform-native dir → OS env-var override → /tmp/ru-stt-tui) so the app never crashes on a non-ASCII Windows username. Use --config PATH to override.
The TUI's device picker requires a working PortAudio backend. If you see
a crash at startup (e.g. PortAudioError), your system may be missing
PortAudio libraries or you may be on a headless server without audio.
- Linux:
apt install libportaudio2(Debian/Ubuntu) or equivalent - macOS: PortAudio ships with the OS; check
brew list portaudio - Windows: wheels ship with PortAudio; check microphone permissions
Known v1 issue (F9): when PortAudio raises inside
sounddevice.query_devices() (e.g. on a headless server), list_input_devices()
surfaces the underlying KeyError/PortAudioError and the TUI can
crash before rendering the picker. A graceful "no devices" fallback is
tracked for v1.1. Workaround for now: ensure PortAudio is installed
before running the TUI.
If you're on Windows using cmd.exe (not Windows Terminal), the
console may default to a non-UTF-8 code page. The TUI auto-fixes this
on startup by running chcp 65001. If that fails, run it manually
before launching the app:
chcp 65001
ru-stt-tuiIf the GigaAM-v3 download is interrupted, the cache may be incomplete. Delete the cache and re-run:
# Linux/macOS
rm -rf ~/.cache/huggingface/hub/models--ai-sage--GigaAM-v3
# Windows (PowerShell)
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\huggingface\hub\models--ai-sage--GigaAM-v3"Then run ru-stt-tui --setup-only to re-download.
The first run needs ~3 GB free in your home directory. The app checks for this before downloading; if you're below the threshold it prints a clear error and aborts (no partial download).
GigaAM-v3-e2e-rnnt on a modern CPU transcribes a 2-second utterance in a few seconds. For real-time-ish feedback, use a GPU. The first CUDA-capable GPU detected is used automatically.
Unlike the upstream GigaAM README, this project bypasses the model's
internal ffmpeg-based load_audio path. Microphone audio is written
to a temporary 16 kHz mono WAV via soundfile and fed to
model.embed_audio(...) directly. You do not need to install
ffmpeg to use the app.
Clone and install with dev dependencies:
git clone <repo-url>
cd ru-stt-tui
pip install -e ".[dev]"Run tests:
pytest tests/ -vLint:
ruff check src testsEnd-to-end (requires real mic + downloaded model):
RUN_E2E=1 pytest tests/test_e2e_recording.py -vThe app has a single async event loop (Textual's asyncio loop)
running on the main thread, a PortAudio callback that captures
microphone frames into a worker-fed queue, and a dedicated
threading.Thread ASR worker that decodes RNN-T output and posts
results back to the UI via app.call_from_thread.
[mic] -> sounddevice.InputStream (16 kHz mono int16)
-> AudioCapture (PTT, 60s cap, watchdog)
-> Recording (in-memory NumPy + temp WAV path)
v
queue.Queue -> ASRWorker (background thread)
v
HuggingFace GigaAM-v3-e2e-rnnt (~2.5 GB)
model.embed_audio(tmp.wav) -> features -> RNN-T greedy decode
(PyTorch GPU when available, PyTorch CPU otherwise)
v
Segment (text + start_time + end_time + confidence?)
v
TranscriptBuffer (asyncio.Lock)
v
Textual TUI (RichLog + status bar)
v
[User] -> Ctrl+C (clipboard) | Ctrl+S (save)
The ASR worker runs on its own thread to keep the TUI's event loop
responsive. All worker-to-UI handoffs go through app.call_from_thread
to maintain thread safety.
MIT (matches GigaAM's license).
- GigaAM by SberDevices — the
state-of-the-art Russian ASR model. The
ai-sage/GigaAM-v3Hugging Face Hub repo is the v3 distribution. - Textual — modern async TUI framework for Python.
- Hugging Face Transformers — the model loading and inference stack.
- F1 — Word-level confidence (RNN-T token probs)
- F2 — Real-time streaming word-by-word UI
- F3 — INT8 quantization for faster CPU inference
- F4 — Multi-language support (Russian only in v1)
- F5 — Auto-save on quit
- F6 — CI smoke matrix (Linux + macOS)
- F7 — ONNX + CUDAExecutionProvider for low-VRAM GPUs
- F8 — Long-form audio (>60s) via chunked decoding
- F9 — Graceful PortAudio-missing handling (no crash on startup; TUI shows "no devices" fallback)