The KAGAMI mark КАГАМИ
kagami.bg/academy · lesson · machine-readable viewTESTED 2026-10-28
IDENTITY
module
KW I33 · Bulgarian speech to text: trialing two local models
series
KAGAMI Way / Local AI
level
Intermediate
duration
~18 min
trust_label
TESTED 2026-10-28 (both models run locally on one machine with an NVIDIA GB10 chip and 128 GB unified memory; same audio, same scoring)
language
human view: bg · english edition: /en/academy/moduli/KW_I33_Speech_To_Text_Trial.html
prev
KW I22 · Two nodes: worker + brain
next
module index
PURPOSE

Show how to compare speech-to-text models for Bulgarian fairly — a test set with reference text, one error metric, one normalisation, the same audio for both — and what the numbers do not tell you.

RESULTS
KEY CONCEPTS
COMMANDS / PATHS
CHECKLIST
NEXT MODULE

Module index · offer: Quick experiment €39 incl. VAT (kagami.bg/stalbata/)

SOURCES
TAGS

speech-to-text · ASR · Bulgarian · WER · FLEURS · Whisper · Nemotron · vLLM · local AI · translation · evaluation

TESTED · 28.10.2026

Bulgarian speech to text: trialing two local models

A new model promises better speech recognition. How do you find out whether it is better for Bulgarian, not just in the announcement? The same audio, a reference text and one yardstick. We trialed Nemotron 3.5 Transcribe against Whisper large-v3 on our own machine — here is the method and what came out.

⏱ ~18 min Intermediate KAGAMI Way · I33 test · word errors · translation
Whisper large-v3🔒 local Nemotron 3.5 Transcribe🔒 local FLEURS — test recordings🌐 public data

01What you will learn

02Before you start

⛔
Keep a memory reserve
While loading, a large model briefly takes more than you allowed it. If other services run on the same machine, check free memory before starting and keep at least 20 GB in reserve. Stop the model after the batch.

03Steps

  1. Get recordings with reference text

    Without reference text you cannot tell who is wrong — only who writes differently. So start with a public test: Google's FLEURS has Bulgarian recordings and their text. We took 60 different sentences, one recording per sentence, with a fixed random choice — so the trial can be repeated.

    Audio in the format the models expect
    ffmpeg -i recording.mp3 -ac 1 -ar 16000 recording.wav
  2. Measure with one yardstick

    The yardstick is the word error rate: how many words are substituted, dropped or added compared with the reference. Before scoring, both texts are “normalised” the same way — lower case, no punctuation. Otherwise a model loses points for a comma, not for a word.

    Word error rate · Python
    import re, unicodedata
    
    def words(s):
        s = unicodedata.normalize("NFC", s.lower()).replace("ѝ", "и")
        return re.sub(r"[^\w\s]", " ", s).split()
    
    def distance(a, b):  # words to substitute, delete or insert
        d = list(range(len(b) + 1))
        for i, x in enumerate(a, 1):
            p, d[0] = d[0], i
            for j, y in enumerate(b, 1):
                p, d[j] = d[j], min(d[j] + 1, d[j - 1] + 1, p + (x != y))
        return d[-1]
    
    def wer(refs, hyps):
        e = sum(distance(words(r), words(h)) for r, h in zip(refs, hyps))
        return 100 * e / sum(len(words(r)) for r in refs)
    ⚠️
    Trap: numbers
    We do not normalise numbers. “M16” against “M sixteen” counts as an error. That is why figures from different sites cannot be compared with each other — everyone normalises their own way.
  3. Run both models under the same conditions

    Tell both the language explicitly and set “temperature” to 0 — no randomness. Whisper takes the language as a setting. Nemotron takes an instruction in words together with the audio: language, verbatim or clean, how to write numbers, which names to expect.

    Instruction to Nemotron · transcription
    Audio transcription. Language: Bulgarian, in its standard writing system.
    Formatting: punctuation and capitalization. Output: transcript only.
    Request to the local server (vLLM) · Python
    import base64, requests
    
    audio = base64.b64encode(open("recording.wav", "rb").read()).decode()
    r = requests.post("http://localhost:<port>/v1/chat/completions", json={
        "model": "nemotron", "temperature": 0,
        "chat_template_kwargs": {"enable_thinking": False},
        "messages": [{"role": "user", "content": [
            {"type": "text", "text": "Audio transcription. Language: Bulgarian. Output: transcript only."},
            {"type": "audio_url", "audio_url": {"url": "data:audio/wav;base64," + audio}}]}]})
    print(r.json()["choices"][0]["message"]["content"])
    💡
    Names and terms
    Add “Context terms:” to the instruction and list the names that will be heard — organisations, people, places. The model then spells them correctly instead of guessing.
  4. Read the numbers — and the errors

    On the 60 Bulgarian sentences:

    Result · 28.10.2026
    Model                         Word errors   Better in
    Whisper large-v3              15.23 %       14 sentences
    Nemotron 3.5 Transcribe       11.86 %       36 sentences
    (equal: 10 sentences)

    Nemotron writes Bulgarian endings and compound words more cleanly where Whisper misspells them. But read the opposite cases too. In one sentence Nemotron “completed the meaning” on its own and wrote something fluent but wrong — a rifle became “descending from M sixteen”. In a live recording it once flipped the meaning of a whole sentence.

    ✅
    The rule
    Fewer word errors does not mean safer text. Minutes, a quote or a decision written by a model are read by a person against the audio.
    ⚠️
    Trap: speed
    Our Whisper ran on the CPU, Nemotron on the graphics card. So 17 seconds against 1 second per recording compares the machines, not the models. Compare speed only on the same hardware.
  5. Try a live recording and translation

    Test recordings are read aloud. Live speech in a hall is harder. We ran 3 minutes of a live Bulgarian lecture through both — the two texts differed in about 12% of words, with no reference to say who was right. Here a person who listens decides.

    Nemotron can also translate from audio: we ran an English talk with the instruction “Please translate the given speech to Bulgarian.” and got fluent Bulgarian text. Whisper only translates into English.

    ⚠️
    Trap: the wrong language
    Tell Whisper “Bulgarian” when the recording is in English and it returns a half-translation full of errors. First check the language of the recording — Whisper can detect it if you do not set one.

04Check

1. What do you need to say which model makes fewer errors?

2. Why are the texts normalised before scoring?

3. The model with fewer word errors wrote the minutes of a meeting. What do you do?

4. One model runs on a CPU, the other on a graphics card. What does the speed difference tell you?

05What next

06Sources

  1. NVIDIA · Nemotron 3.5 Transcribe — model card — languages, instructions, serving with vLLM, licence.
  2. NVIDIA · Nemotron 3.5 Transcribe and Granary v2 — what “promptable transcription” means.
  3. Google · FLEURS — test recordings with reference text, including Bulgarian.
  4. OpenAI · Whisper large-v3 and faster-whisper — the model and its fast runtime.
  5. The New Stack · Nvidia launches a promptable transcription model — the news, 28.10.2026.