Ratatoskr: głos do schowka, bez chmury
Lokalne narzędzie speech-to-text: naciskasz skrót, mówisz i wklejasz transkrypcję. Bez chmury, bez kont.
Każde narzędzie do dyktowania, które testowałem, chciało rejestracji, otwarcia przeglądarki albo wysłania mojego audio na czyjś serwer. Ja chciałem tylko nacisnąć klawisz, powiedzieć tekst i wkleić wynik. Zbudowałem więc narzędzie, które robi dokładnie to.
Pomysł
Ratatoskr siedzi w trayu systemowym i robi jedną rzecz: naciskasz skrót, mówisz, dostajesz tekst w schowku. Wszystko działa lokalnie przez faster-whisper, czyli ten sam model Whisper udostępniony przez OpenAI, ale zoptymalizowany przez CTranslate2. Audio nigdy nie opuszcza twojego komputera. Jedyny request sieciowy to jednorazowe pobranie modelu z Hugging Face przy pierwszym uruchomieniu.
To ostatnie było dla mnie ważne. Dyktuję notatki, szkice wiadomości i półuformowane myśli, a żadna z tych rzeczy nie powinna lądować na cudzym serwerze.
Jak to działa
Naciskasz Ctrl+Alt+R (albo skrót, który sobie ustawisz). W prawym dolnym rogu pojawia się mały overlay pokazujący, że trwa nagrywanie, z timerem oraz przyciskami pauzy i stopu.
Kiedy zatrzymasz nagranie, audio trafia prosto do Whispera. Kilka sekund później transkrypcja ląduje w schowku. Wklejasz ją tam, gdzie chcesz: do maila, Slacka, edytora albo terminala. Jeśli chcesz dodatkowo zapisać plik .txt, jest do tego przełącznik.
To cały workflow. Nie ma nic do zarządzania i żadnego UI, przez które trzeba się przeklikiwać; aplikacja pozostaje niewidoczna, dopóki jej nie potrzebujesz.
Pod maską
Stack jest celowo mały:
- PySide6 do traya systemowego, overlaya i okna ustawień
- faster-whisper do transkrypcji (GPU przez CUDA, jeśli dostępne, fallback na CPU)
- sounddevice do przechwytywania mikrofonu w 16 kHz mono, czyli formacie oczekiwanym przez Whispera
- Windows RegisterHotKey API do globalnego skrótu, który działa nawet wtedy, kiedy aplikacja nie ma fokusu
Model ładuje się w tle podczas startu aplikacji, żeby pierwsza transkrypcja nie przycinała. Audio jest trzymane w pamięci jako tablica numpy float32 i przekazywane bezpośrednio do Whispera, bez plików tymczasowych w typowej ścieżce działania.
Na dysk trafia jeden plik: awaryjny WAV zapisywany tuż przed startem transkrypcji. Jeśli aplikacja wysypie się w trakcie, kolejne uruchomienie podnosi ten plik i kończy zadanie. Po sukcesie albo błędzie plik jest usuwany.
Ustawienia
Kliknięcie prawym przyciskiem ikony w trayu otwiera ustawienia. Możesz zmienić rozmiar modelu Whisper (od tiny dla szybkości do large-v3 dla dokładności), wybrać język źródłowy albo zostawić autodetekcję, przemapować skrót oraz włączyć/wyłączyć zapis do schowka i pliku.
Domyślny jest model small. To dobry kompromis: wystarczająco szybki do użycia na bieżąco i wystarczająco dokładny dla większości języków. Jeśli masz GPU, większe modele też stają się praktyczne.
Vibe-codowane, potem audytowane
Tak jak Mamrot, Ratatoskr zaczął się jako projekt vibe-codingowy: opisałem, czego chcę, i pozwoliłem Claude’owi zbudować pierwszą wersję. Przed publikacją poprosiłem Claude’a i GPT o wzajemny audyt kodu pod kątem bezpieczeństwa wątków, zgodności licencji, prywatności (czy audio nie zostaje na dysku po błędzie), struktury TOML i bugów renderowania fontów. Dwa modele wyłapujące nawzajem swoje dziury znalazły więcej problemów niż każde z nich osobno. Vibe-coding szybko prowadzi do działającego prototypu; cross-audit robi z niego coś, co naprawdę można wypuścić.
Czego się nauczyłem
RegisterHotKey zamiast bibliotek keyboard. Zacząłem od pythonowego pakietu keyboard do globalnych skrótów. Działał dobrze, aż w końcu przestał. Niektóre antywirusy flagują niskopoziomowe hooki klawiatury, a w części konfiguracji biblioteka wymagała uprawnień administratora. Przejście na natywne Win32 API RegisterHotKey naprawiło wszystko. To kilka linijek ctypes więcej, ale po prostu działa.
Trzymaj audio w pamięci. Wczesne wersje zapisywały WAV na dysk, przekazywały ścieżkę do Whispera, a potem usuwały plik. Wycięcie rundy przez dysk i przekazywanie tablicy numpy bezpośrednio sprawiło, że cały flow stał się zauważalnie szybszy, a do sprzątania został jeden plik mniej.
Rozmiary fontów w stylesheetach Qt: używaj pt, nie px. Jeśli ustawisz font-size: 13px w stylesheetcie Qt, część widgetów próbuje wewnętrznie odczytać rozmiar w punktach, dostaje -1 i Qt wypisuje ostrzeżenie. Przejście na jednostki pt naprawiło to bezszelestnie.
Wypróbuj
git clone https://github.com/konradozog/Ratatoskr.git
cd Ratatoskr
python -m venv .venv
.venv\Scripts\activate
pip install .
ratatoskr
Windows 10/11, Python 3.10+. Tylko tyle potrzeba.