asfberlin/fast-ukrainian-asr
fast-ukrainian-asr — Ukrainian speech recognition, 220M, CTC
A Ukrainian recogniser built by adapting GigaAM's multilingual SSL encoder, tuned for telephone audio and small enough to run in real time on a CPU.
It is not the most accurate Ukrainian model in every setting — Whisper large-v3 is clearly better on spontaneous speech, and the numbers below say so. What it does is recognise read and telephone speech more accurately than either Whisper large-v3 or the Whisper Ukrainian fine-tunes, while running on CPU faster than Whisper runs on a GPU, and losing almost nothing when the audio comes down a phone line.
Results
Scored with a single normalizer across all systems (Whisper emits punctuation and capitals this model never produces, so raw-string WER would measure formatting). Telephony = G.711 band-limit, 16k->8k->16k, mu-law, applied ONCE and shared byte-identically by every system. Ukrainian-tagged rows only.
Read the third column before deploying this. On spontaneous speech (rs-test, test-y) Whisper large-v3 is 5-11 points better. This model was trained on broadcast and read speech; it has not seen much conversational audio, and it shows.
The telephony column is the reason it exists. Clean -> phone costs this model +0.95 WER on cv10; it costs Whisper large-v3 +3.57. Telephony augmentation during training buys that, and for a phone product it matters more than a better clean number.
Qwen3-ASR does not support Ukrainian at all — its 30-language list has no entry for it, so it transcribes Ukrainian speech into Russian orthography. The row is included so nobody repeats the experiment.
Scope: Ukrainian only
Deliberately monolingual. On Russian utterances it scores ~89% WER and always will: the vocabulary is 38 Ukrainian characters with no Russian-only letters. If your audio is mixed Russian/Ukrainian — as much Ukrainian evaluation data quietly is — use a multilingual model.
Training
- Backbone: GigaAM
multilingual_ssl(220M, 16 layers, d_model 768), an SSL encoder pretrained on 2M hours across 70+ languages with no Ukrainian. - Stage 1: 350 h — Yehor/broadcast-speech-uk (309 h) + Common Voice 22 Ukrainian (41 h), 8 epochs, batch 16, lr 1e-4, charwise CTC head, 38 classes.
- Stage 2: telephony adaptation, 4 epochs at lr 3e-5, 60% of training clips degraded through the phone path, validation 100% degraded so checkpoint selection ranks on what production serves.
Common Voice's train and other splits only: its validated pool shares 1,326 sentences with the cv10 evaluation set and test shares 396, so training on those would quietly contaminate the benchmark. 146 rows containing Latin/Cyrillic homoglyphs (i typed for і) were repaired rather than dropped.
Usage
import gigaam
model = gigaam.load_model("fast-ukrainian-asr.ckpt", device="cpu") # or "cuda"
print(model.transcribe("call.wav"))longform.py handles files longer than ~20 s by energy-based segmentation. server.py exposes an OpenAI-compatible /v1/audio/transcriptions endpoint. Audio must be 16 kHz mono; 8 kHz telephone audio should be upsampled, not fed at its native rate.
Limitations
- Spontaneous/conversational speech is its weakest case (see the table).
- No punctuation or capitalisation — CTC over 38 characters.
- No Russian, by design.
- Numbers are transcribed as words, not digits.
