LabSpeech to text

Local speech to text for agent chat, measured

Unluminous agent chat is getting a microphone button. We took the five strongest open speech recognition models of October 2026, ran all of them through transcribe.cpp, the runtime Unluminous could embed, and measured word error rate on 1,198 real recordings, graphics memory, speed, and what it costs to load a model only when someone presses the button. We also ran Whistle, a 16.9 MB model that runs only on the CPU, the same way (section 11).

5.86%WER
Granite Speech 5.0 470M TurboCTC at Q8_0, mean of six test sets; the next best was Cohere Transcribe at 6.25%
1.11GB
peak graphics memory for Granite Speech 5.0 470M TurboCTC on the longest clips, CUDA context included
54ms
from letting go of the button to text, with the model loaded and warmed while the person spoke
496MB
graphics memory a freed model leaves on the card until its process ends

Granite Speech 5.0 470M TurboCTC made the fewest errors, 5.86% of words, with the least graphics memory of the five. It only understands English and writes lower case words with no punctuation; a 200 MB punctuation model puts the marks back, and five bit Granite is as accurate as eight bit. Loading a model when the button is pressed costs nothing the person notices: every load finished within 2.2 seconds, while they were still talking.

01The question

A microphone button for agent chat

A person holds the button, says what they want, and lets go. The text has to appear in the chat box quickly and be right, and the model must cost almost nothing while nobody is talking, because the same graphics card is usually holding a local language model.

So the lab asks four things of each model: how many words it gets wrong, how much graphics memory it takes, how long the person waits after letting go, and what it costs to load the model only when the button is pressed and keep it for some minutes afterwards.

02The five

Five models, one runtime

The five were picked from what people recommend and what was released this year: the Open ASR Leaderboard, the HuggingFace list of trending speech recognition models, and the last thirty days of r/LocalLLaMA, r/speechtech, Hacker News and GitHub. Each is under about two billion parameters, so it fits beside a language model on one card.

All five run through transcribe.cpp 0.3.1, an MIT licensed C++ library built on ggml, the same base as llama.cpp. It runs every one of these models from a single GGUF file on CUDA, Vulkan, Metal and the CPU, and it has Rust bindings, which is what Unluminous is written in. Measuring through it measures what would ship. The GGUF files are the handy-computer conversions, each checked against the publisher’s SHA-256.

The five models

From each model's card. Vocabulary means the model accepts a list of words to favour, such as the names in a project. Published WER is the Open ASR Leaderboard's average over its eight English sets, read on 4 October 2026.

ModelVendorSizeLanguagesLicenceReleasedVocabularyPublished WER
Parakeet TDT 0.6B v3NVIDIA0.60B25CC-BY-4.02025-08-04no4.86%
Cohere TranscribeCohere2.0B14Apache 2.02026-03-26no4.67%
Qwen3-ASR 0.6BAlibaba Qwen0.60B52Apache 2.02026-01-28yes5.05%
Whisper large-v3-turboOpenAI0.81B99MIT2024-10-01yes6.36%
Granite Speech 5.0 470M TurboCTCIBM0.47B1Apache 2.02026-08-25no5.03%

Considered and left out

  • Canary-Qwen 2.5B and Granite Speech 4.1 2B: larger than Cohere Transcribe and less accurate on the leaderboard.
  • Voxtral Mini 4B Realtime and Audio8 ASR Infinite: about 8 GB of weights, built for streaming while the person speaks.
  • Nemotron 3.5 ASR Streaming 0.6B: a streaming model, 7.96% on the leaderboard’s English sets.
  • Moonshine: very small, but 9.99% on the leaderboard.
  • Parakeet Redux, Parakeet Ultra and Phonon-2: three new versions of Parakeet released in September 2026, each run only by its maker’s own runtime (Photon or Fermion), which Unluminous cannot embed.
03Accuracy

Granite Speech 5.0 470M TurboCTC makes the fewest errors

Word error rate is the share of words a model gets wrong: substituted, dropped or added. Every model heard the same 1,198 clips from six test sets, from clean audiobooks to meetings and earnings calls. Q8_0, the eight bit version of each model, is the one compared here.

Granite Speech 5.0 470M TurboCTC, a CTC model released by IBM in August 2026, is the most accurate at 5.86%. Cohere Transcribe is next at 6.25%, then Parakeet TDT 0.6B v3 at 6.67%, Qwen3-ASR 0.6B at 7.71% and Whisper large-v3-turbo at 9.34%.

On the leaderboard’s own eight English sets the top four are closer together and in another order: Cohere Transcribe 4.67%, Parakeet TDT 0.6B v3 4.86%, Granite Speech 5.0 470M TurboCTC 5.03% and Qwen3-ASR 0.6B 5.05%. Our six sets include Common Voice, people reading into their own microphones, and the meetings and earnings calls as they were recorded rather than cleaned up, which is closer to someone talking at a desk. Granite does best on those.

Whisper’s number is high because of one failure: for 20 of the clips it wrote only “Thank you.” instead of the speech. This is Whisper’s known habit of producing a phrase common in its training subtitles, and it happened with and without timestamps. In a chat box it would send “Thank you.” to the agent.

Granite gets its accuracy without punctuation or capital letters: every transcript is lower case words. The other four write sentences. Ready to paste in the table below is the share of transcripts that start with a capital and contain punctuation.

Word error rate, Q8_0Mean of the six test sets, 200 clips each, lower is better. Every transcript and reference went through the Whisper English normaliser before scoring.
Granite Speech 5.0 470M TurboCTC5.86%
Cohere Transcribe6.25%
Parakeet TDT 0.6B v36.67%
Qwen3-ASR 0.6B7.71%
Whisper large-v3-turbo9.34%

Word error rate by test set

Q8_0 on the graphics card. Ready to paste is the share of transcripts that start with a capital and contain punctuation, so they read like typed text in a chat box.

ModelLibriSpeech cleanLibriSpeech otherCommon VoiceAMIEarnings-22VoxPopuliMeanReady to paste
Parakeet TDT 0.6B v31.60%3.36%9.52%9.77%10.39%5.35%6.67%91%
Cohere Transcribe1.03%2.33%7.02%10.94%10.98%5.18%6.25%90%
Qwen3-ASR 0.6B1.75%4.31%10.21%12.78%10.76%6.47%7.71%100%
Whisper large-v3-turbo1.91%3.93%11.22%17.99%10.92%10.09%9.34%72%
Granite Speech 5.0 470M TurboCTC1.08%2.55%6.76%10.65%8.53%5.61%5.86%0%
04Memory

Small models, and eight bits is enough

Graphics memory here is everything the model’s process held on the card: the weights, the CUDA context, and the working buffers while it transcribed the ten longest clips, 22 to 30 seconds each. Granite Speech 5.0 470M TurboCTC peaked at 1.11 GB, Parakeet TDT 0.6B v3 at 1.38 GB, Whisper large-v3-turbo at 1.52 GB, Qwen3-ASR 0.6B at 2.31 GB and Cohere Transcribe at 3.07 GB.

Q8_0 is as accurate as the sixteen bit F16 file for every model. Q4_K_M is smaller and costs at most 0.61 points of word error rate, which makes it the choice for a card that is nearly full.

Accuracy against graphics memoryEach model at three quantisations. Lower left is better. Graphics memory is the most the model's process held on its card while transcribing the ten longest clips, CUDA context included, read from Windows' per process counter in one fresh process each.
  • Q4_K_M
  • Q8_0
  • F16
456789101102,0004,0006,000Graphics memory used (MB)Word error rate (%)Parakeet TDT 0.6B v3, Q4_K_M: 6.89% WER, 1.15 GB peak, 1.04 GB loadedParakeet TDT 0.6B v3, Q8_0: 6.67% WER, 1.38 GB peak, 1.28 GB loadedParakeet TDT 0.6B v3, F16: 6.65% WER, 1.81 GB peak, 1.71 GB loadedParakeet TDT 0.6B v3Cohere Transcribe, Q4_K_M: 6.30% WER, 2.28 GB peak, 2.12 GB loadedCohere Transcribe, Q8_0: 6.25% WER, 3.07 GB peak, 2.91 GB loadedCohere Transcribe, F16: 6.27% WER, 4.65 GB peak, 4.49 GB loadedCohere TranscribeQwen3-ASR 0.6B, Q4_K_M: 8.32% WER, 1.98 GB peak, 1.51 GB loadedQwen3-ASR 0.6B, Q8_0: 7.71% WER, 2.31 GB peak, 1.84 GB loadedQwen3-ASR 0.6B, F16: 7.71% WER, 3.14 GB peak, 2.67 GB loadedQwen3-ASR 0.6BWhisper large-v3-turbo, Q4_K_M: 9.74% WER, 1.20 GB peak, 1.14 GB loadedWhisper large-v3-turbo, Q8_0: 9.34% WER, 1.52 GB peak, 1.47 GB loadedWhisper large-v3-turbo, F16: 9.75% WER, 2.23 GB peak, 2.18 GB loadedWhisper large-v3-turboGranite Speech 5.0 470M TurboCTC, Q4_K_M: 6.09% WER, 0.90 GB peak, 0.86 GB loadedGranite Speech 5.0 470M TurboCTC, Q8_0: 5.86% WER, 1.11 GB peak, 1.07 GB loadedGranite Speech 5.0 470M TurboCTC, F16: 5.87% WER, 1.47 GB peak, 1.42 GB loadedGranite Speech 5.0 470M TurboCTC

Graphics memory per quantisation

Each cell is graphics memory with the model loaded, then the peak while transcribing the ten longest clips.

ModelQ4_K_MQ8_0F16
Parakeet TDT 0.6B v31.04 GB / 1.15 GB1.28 GB / 1.38 GB1.71 GB / 1.81 GB
Cohere Transcribe2.12 GB / 2.28 GB2.91 GB / 3.07 GB4.49 GB / 4.65 GB
Qwen3-ASR 0.6B1.51 GB / 1.98 GB1.84 GB / 2.31 GB2.67 GB / 3.14 GB
Whisper large-v3-turbo1.14 GB / 1.20 GB1.47 GB / 1.52 GB2.18 GB / 2.23 GB
Granite Speech 5.0 470M TurboCTC0.86 GB / 0.90 GB1.07 GB / 1.11 GB1.42 GB / 1.47 GB
05Speed

Fast enough that speed does not decide it

With the model loaded, a six second request takes 35 ms with Granite Speech 5.0 470M TurboCTC and 165 ms with the slowest, Qwen3-ASR 0.6B. Every model is many times faster than speech.

One setting matters. In transcribe.cpp 0.3.1 on CUDA, flash attention for Parakeet and Cohere runs on the CPU, one trip per encoder layer, so turning it off with TRANSCRIBE_NO_FLASH=1 makes them faster: 2.6 times for Parakeet TDT 0.6B v3 and 2.3 times for Cohere Transcribe in the runs below, and 10 times for Cohere in a first test on a quieter machine. Whisper, Qwen3-ASR and Granite are faster with it on. These runs shared the machine with other work, so the CPU load column matters when comparing them. The transcripts do not change: on 300 Parakeet clips, 296 were identical and the other 4 differed by a comma or one word.

A six second request, model already loaded, graphics cardQ8_0 on an NVIDIA GeForce RTX 5090: the median of three transcripts in each of five fresh processes.
Granite Speech 5.0 470M TurboCTC35 ms
Parakeet TDT 0.6B v383 ms
Whisper large-v3-turbo85 ms
Cohere Transcribe164 ms
Qwen3-ASR 0.6B165 ms

Seconds of audio transcribed per second

Real time factor over the same 100 Common Voice clips for every model, one clip at a time, Q8_0 on the graphics card. Flash on and off are the two settings of transcribe.cpp's TRANSCRIBE_NO_FLASH; the transcripts are the same either way. Other CPU load is the share of the CPU other programs used during the run; part of each model's work runs on the CPU, so a busy machine slows it.

ModelFlash onOther CPU loadFlash offOther CPU load
Parakeet TDT 0.6B v330×43%76×52%
Cohere Transcribe14×41%32×83%
Qwen3-ASR 0.6B74×25%45×49%
Whisper large-v3-turbo108×32%66×62%
Granite Speech 5.0 470M TurboCTC186×23%146×53%
06Loading

Loading on demand costs the person nothing

Pressing the button starts the load. Starting the GPU backend takes about 309 ms, and loading the model from the operating system’s cache takes between 537 ms (Granite Speech 5.0 470M TurboCTC) and 1.86 s (Cohere Transcribe). The person is speaking for the whole time, so by the time they let go the model is ready, and the only wait is the first transcript.

A cold start, with the file not in the cache, adds the time to read the file from the drive: at most 0.50 seconds for Cohere’s 2299 MB file on this NVMe drive.

Freeing the model gives back its weights but not the CUDA context: 496 MB stays on the card until the process ends. To give the card back completely, speech to text should run in a small helper process that exits when it is no longer needed.

The runtime also opens a CUDA context on every graphics card in the machine, used or not. This machine has two, and each model’s process held 496 MB on the second card for as long as it ran. A helper process started with CUDA_VISIBLE_DEVICES set to the one card it should use avoids that.

From pressing the button to text, graphics cardA new process each time, the model file already in the operating system's cache. Median of five.
  • Start the backend
  • Load the model
  • First transcript
  • The person is still talking (6.0 s clip)
Parakeet TDT 0.6B v31.20 s
Cohere Transcribe2.60 s
Qwen3-ASR 0.6B1.68 s
Whisper large-v3-turbo1.42 s
Granite Speech 5.0 470M TurboCTC981 ms

Every phase of a load

Q8_0 on the graphics card, median of five fresh processes. Read from SSD is how long an unbuffered read of the model file takes on this machine's NVMe drive: the most a cold start, with the file not in the operating system's cache, can add. Reload is loading the model again in a process that already started the backend. Warmed first transcript is the first transcript after one second of silence was run through the model while the person was still talking. Left after unload is graphics memory still held on the model's card once the model is freed: the CUDA context. Other card is what the same process holds on this machine's second graphics card, which it never uses. Memory columns are read from Windows' per process counter.

ModelStart backendLoadRead from SSDFirst transcriptReloadWarmed first transcriptLeft after unloadOther card
Parakeet TDT 0.6B v3309 ms685 ms198 ms208 ms484 ms91 ms496 MB496 MB
Cohere Transcribe327 ms1.86 s501 ms407 ms1.60 s195 ms496 MB496 MB
Qwen3-ASR 0.6B343 ms947 ms116 ms395 ms755 ms214 ms496 MB496 MB
Whisper large-v3-turbo308 ms822 ms126 ms295 ms566 ms100 ms496 MB496 MB
Granite Speech 5.0 470M TurboCTC297 ms537 ms66 ms147 ms345 ms54 ms496 MB496 MB
07Keep loaded

Keep it loaded for a few minutes, then end the process

To see what a policy costs on real use, we replayed 471 messages Jason sent to coding agents over 60 days, one press per message: his comments on Tasks board tickets and the prompts he typed into agent terminals. Only the time of each message was used. A second, made up timeline stands in for someone who talks to agents all day.

Because the load hides under speech, keeping the model loaded hardly changes the wait. With Granite Speech 5.0 470M TurboCTC in a helper process that runs one second of silence through the model while the person talks, unloading at once and loading on every press averaged 53 ms from release to text, and keeping it loaded all day averaged 35 ms. Without the second of silence, unloading at once averaged 139 ms, because the first transcript in a new process is slower than the ones after it.

What the policy does change is how long the card is held. Kept for 5 minutes after each press, the model was loaded 0.55 hours a day on Jason’s messages and 1.43 hours for the heavy user, against all day when it is never unloaded.

Share of presses that start the modelReal: 471 messages Jason sent to coding agents over 60 days. Heavy: a made up user with four sessions a day of fifteen messages each, 45 seconds apart at the median.
  • Real messages
  • Heavy user (made up)
0%20%40%60%80%100%unload1 min2 min5 min10 min15 min30 min60 minKeep the model loaded after the last press forPresses that load (%)Real messages, unload: 93%Real messages, 1 min: 89%Real messages, 2 min: 83%Real messages, 5 min: 73%Real messages, 10 min: 68%Real messages, 15 min: 61%Real messages, 30 min: 51%Real messages, 60 min: 39%39%Heavy user (made up), unload: 98%Heavy user (made up), 1 min: 39%Heavy user (made up), 2 min: 19%Heavy user (made up), 5 min: 9%Heavy user (made up), 10 min: 7%Heavy user (made up), 15 min: 7%Heavy user (made up), 30 min: 7%Heavy user (made up), 60 min: 7%7%
Hours a day Granite Speech 5.0 470M TurboCTC holds the graphics cardThe same two timelines. Always loaded holds the card for the whole span.
  • Real messages
  • Heavy user (made up)
0.0 h2.0 h4.0 h6.0 hunload1 min2 min5 min10 min15 min30 min60 minKeep the model loaded after the last press forHours a day loadedReal messages, unload: 0.0 hReal messages, 1 min: 0.1 hReal messages, 2 min: 0.2 hReal messages, 5 min: 0.6 hReal messages, 10 min: 1.0 hReal messages, 15 min: 1.4 hReal messages, 30 min: 2.5 hReal messages, 60 min: 4.3 h4.3 hHeavy user (made up), unload: 0.1 hHeavy user (made up), 1 min: 0.8 hHeavy user (made up), 2 min: 1.1 hHeavy user (made up), 5 min: 1.4 hHeavy user (made up), 10 min: 1.8 hHeavy user (made up), 15 min: 2.2 hHeavy user (made up), 30 min: 3.2 hHeavy user (made up), 60 min: 5.3 h5.3 h

Keep loaded for N minutes, Granite Speech 5.0 470M TurboCTC, real messages

Wait is the mean time from releasing the button to the text, over every press. Speech to text runs in a helper process that ends after N idle minutes, which gives back all its graphics memory, and runs one second of silence through the model while the person talks. No warm up is the same without that second of silence. The last column is the made up heavy user.

Keep loaded forPresses that loadWait, 6 s requestWait, 2 s requestWait, no warm upLoaded per dayHeavy user: load / loaded
unload at once92.8%53 ms53 ms139 ms0.01 h98.1% / 0.1 h
1 min88.5%52 ms52 ms134 ms0.13 h39% / 0.77 h
2 min82.8%51 ms51 ms128 ms0.24 h19.3% / 1.05 h
5 min73%49 ms49 ms117 ms0.55 h9.3% / 1.43 h
10 min67.9%48 ms48 ms111 ms1.01 h7% / 1.83 h
15 min61.1%47 ms47 ms103 ms1.44 h6.8% / 2.19 h
30 min51%45 ms45 ms92 ms2.54 h6.7% / 3.24 h
60 min39.3%42 ms42 ms79 ms4.28 h6.7% / 5.31 h
always0.2%35 ms35 ms35 ms24 h0.1% / 24 h
08Examples

Hear it, then read what each model wrote

Three clips the models disagreed on, from three test sets. Press play, then compare what each model wrote. Words the scorer counts as wrong are underlined. A word a model left out also counts as an error, but there is nothing to underline, so the count can be higher than the underlines.

VoxPopuli11.7 s
What was said
while i respect one country two systems' i find it shocking that a country run by a communist party appears to be advocating a system which gives representation only to those with wealth and privilege.
Parakeet TDT 0.6B v33 errors
Mr President, while I respect one country, two systems, I find it shocking that a country run by a Communist Party appears to be advocating a system which brings representation only to those with wealth and privilege.
Cohere Transcribe1 error
While I respect one country, two systems', I find it shocking that a country run by a Communist Party appears to be advocating a system which brings representation only to those with wealth and privilege.
Qwen3-ASR 0.6B1 error
While I respect one country, two systems, I find it shocking that a country run by a communist party appears to be advocating a system which brings representation only to those with wealth and privilege.
Whisper large-v3-turbo35 errors
Thank you.
Granite Speech 5.0 470M TurboCTC1 error
while i respect one country 2 systems i find it shocking that a country run by a communist party appears to be advocating a system which brings representation only to those with wealth and privilege
AMI6.1 s
What was said
Yeah well yeah well that has been e that has been eliminated, so that's that's unfortunately a moot point now.
Parakeet TDT 0.6B v32 errors
Yeah, well yeah, well that has been uh that has been eliminated, so that's that's unfortunately a mute point now.
Cohere Transcribe1 error
Yeah well yeah well that has been e that has been eliminated so that's that's unfortunately a mute point now
Qwen3-ASR 0.6B2 errors
Yeah, well, yeah, well that has been that has been eliminated. So that's that's unfortunately a mute point now.
Whisper large-v3-turbo10 errors
Well, that has been eliminated. So that's unfortunately a mute point now.
Granite Speech 5.0 470M TurboCTC1 error
well yeah well that has been e that has been eliminated so that is that is unfortunately a moot point now
Common Voice5.1 s
What was said
Born to Russian Jewish immigrants.
Parakeet TDT 0.6B v33 errors
World Jewish and Jewish immigrants.
Cohere Transcribeno errors
Born to Russian Jewish immigrants.
Qwen3-ASR 0.6Bno errors
Born to Russian Jewish immigrants.
Whisper large-v3-turbo8 errors
I want to wish and to wish any breath.
Granite Speech 5.0 470M TurboCTC2 errors
born jewish and jewish immigrants
09Smaller Granite

Five bits is as good as eight, and three bits nearly so

Granite is the smallest of the five already, so the question is how far it shrinks before it gets worse. The handy-computer conversions stop at Q4_K_M. transcribe.cpp’s own quantise tool also makes Q5_1, Q5_0, Q4_1 and Q4_0, which we made from the F16 file. Below four bits the runtime refuses to load the file at all, so for Q3_K_M, Q3_K_S and Q2_K we added two presets to the tool and the two weight types to the loader’s list in a local build of the same release.

Every size heard the same 1,198 clips on the same card. Making Q4_K_M ourselves from F16 gave a file with different bytes from the published one and 6.13% against 6.09%, so the files made here can be compared with the published ones.

Granite Speech 5.0 470M TurboCTC at every sizeLower is better in every column; the bar is scaled within its column, and for word error rate it shows how far above the best size each one is. Q2_K is never marked best: it does not work. Word error rate is the mean over the six test sets, 1,198 clips. Peak graphics memory is the most the model's process held on its card while transcribing all of them, CUDA context included. Cold load is reading the file from the drive and loading it onto the card. Request is a six second clip with the model loaded. Both are the fastest of five fresh processes, because on a shared machine the slower runs measure the other work.
QuantisationFileMBWord error rate%; bar is points above the bestPeak graphics memoryMBCold loadsecondsRequest6 s clip
F16published904 MB5.87%1558 MB1.17 s34 ms
Q8_0published482 MB5.86%1140 MB768 ms35 ms
Q6_Kpublished374 MB5.89%1034 MB883 ms42 ms
Q5_1made here from F16341 MB5.94%1000 MB507 ms36 ms
Q5_K_Mpublished320 MB5.88%978 MB512 ms33 ms
Q5_0made here from F16313 MB5.86%972 MB470 ms34 ms
Q4_1made here from F16285 MB5.93%944 MB472 ms34 ms
Q4_K_M, remademade here from F16, as a check266 MB6.13%924 MB470 ms34 ms
Q4_K_Mpublished266 MB6.09%924 MB487 ms37 ms
Q4_0made here from F16257 MB6.14%916 MB582 ms37 ms
Q3_K_Mmade here; needs a patched runtime201 MB6.25%862 MB402 ms36 ms
Q3_K_Smade here; needs a patched runtime199 MB6.32%860 MB412 ms34 ms
Q2_Kmade here; needs a patched runtime155 MB55.60% beyond the scale816 MB395 ms34 ms
Word error rate as the file shrinksMean over the six test sets. Each step to the right is a smaller file. The axis starts at 5% so the rise shows. Q2_K is left off: at 55.6% it does not transcribe.
5.00%5.50%6.00%6.50%F16Q8_0Q6_KQ5_1Q5_K_MQ5_0Q4_1Q4_K_MQ4_0Q3_K_MQ3_K_SQuantisation, largest file firstWord error rate (%)Word error rate, F16: 5.87%Word error rate, Q8_0: 5.86%Word error rate, Q6_K: 5.89%Word error rate, Q5_1: 5.94%Word error rate, Q5_K_M: 5.88%Word error rate, Q5_0: 5.86%Word error rate, Q4_1: 5.93%Word error rate, Q4_K_M: 6.09%Word error rate, Q4_0: 6.14%Word error rate, Q3_K_M: 6.25%Word error rate, Q3_K_S: 6.32%6.32%
What the card holds against the size of the fileBoth in MB. The gap between the lines is the CUDA context and working buffers, which no quantisation removes.
  • Peak graphics memory
  • Model file
0500100015002000F16Q8_0Q6_KQ5_1Q5_K_MQ5_0Q4_1Q4_K_MQ4_0Q3_K_MQ3_K_SQuantisation, largest file firstMBPeak graphics memory, F16: 1558Peak graphics memory, Q8_0: 1140Peak graphics memory, Q6_K: 1034Peak graphics memory, Q5_1: 1000Peak graphics memory, Q5_K_M: 978Peak graphics memory, Q5_0: 972Peak graphics memory, Q4_1: 944Peak graphics memory, Q4_K_M: 924Peak graphics memory, Q4_0: 916Peak graphics memory, Q3_K_M: 862Peak graphics memory, Q3_K_S: 860860Model file, F16: 904Model file, Q8_0: 482Model file, Q6_K: 374Model file, Q5_1: 341Model file, Q5_K_M: 320Model file, Q5_0: 313Model file, Q4_1: 285Model file, Q4_K_M: 266Model file, Q4_0: 257Model file, Q3_K_M: 201Model file, Q3_K_S: 199199

The patched runtime against the released one

Q3_K_M, Q3_K_S and Q2_K only load in a local build of transcribe.cpp 0.3.1 with those two weight types allowed. The same Q8_0 file through both builds gives the same memory and identical transcripts for all 1,198 clips. Times are medians of five. The local build starts faster because it has no Vulkan backend to load.

BuildWord error ratePeak graphics memoryBackend startLoadRequest
Released 0.3.15.86%1140 MB492 ms977 ms50 ms
Local build5.86%1140 MB122 ms676 ms42 ms
  • Down to five bits nothing is lost: Q8_0 5.86%, Q6_K 5.89%, Q5_K_M 5.88%, Q5_0 5.86%. Q5_K_M is published, so it needs nothing built: 320 MB instead of 482 MB, and 978 MB at peak instead of 1140 MB.
  • Q4_K_M and Q4_0 cost about a quarter of a point: 6.09% and 6.14%. Three bits costs about half a point: Q3_K_M 6.25%, Q3_K_S 6.32%, still level with Cohere at eight bits. Two bits does not work: Q2_K gets 55.60% of words wrong.
  • The card’s memory barely follows the file. From F16 to Q3_K_M the file shrinks from 904 MB to 201 MB, but the peak only falls from 1558 MB to 862 MB, because about 500 MB of it is the CUDA context, which is the same for every size.
  • Speed does not decide the size. With the model loaded, every size transcribes a six second request in 33 to 42 ms. Loading the file onto the card takes 322 to 786 ms, roughly following the file size. Starting the GPU backend comes on top, 492 ms with the released package, which also loads a Vulkan backend, and 122 ms with a build that has CUDA only.
10Punctuation

A 200 MB model puts the punctuation back

Granite writes every word in lower case with no punctuation, because it was trained that way. A chat box should show sentences. We tried four small models made to restore punctuation, and the local language model this machine already keeps loaded, each run on Granite’s own transcripts.

pcs_en predicts marks, capitals and sentence breaks in one pass. The two Horizon-Labs models, released on 3 October 2026, predict marks only, so a rule adds the capitals: the first word of each sentence and “I”. bert-restore-punctuation predicts marks and capitals. The language model is asked to add punctuation and capitals without changing a word.

None of them can be trusted with the words. pcs_en writes “<unk>” next to every number Granite wrote as digits, and the language model reworded 0.85% of words. So every option here goes through a safe transfer: its output is lined up with Granite’s words, and only the marks and capitals are copied back. The words a person sees are always the words Granite heard.

Scoring uses the three test sets whose references have punctuation and capitals: Common Voice, AMI and Earnings-22, 598 clips. For each word an output shares with the reference, the mark after it is compared. The four models that punctuate by themselves are scored the same way.

Punctuation F1, all marksFull stops, commas and question marks after the words each output shares with the reference, on Common Voice, AMI and Earnings-22 (598 clips). 1.0 is every mark right. Granite's options go through the safe transfer, so they change no words.
Cohere Transcribe, its own punctuation0.797
Granite + Local language model (Qwen3.8 27B)0.764
Whisper large-v3-turbo, its own punctuation0.757
Granite + pcs_en (1-800-BAD-CODE)0.748
Qwen3-ASR 0.6B, its own punctuation0.735
Granite + Horizon-Labs base, with a casing rule0.728
Granite + Horizon-Labs small, with a casing rule0.722
Parakeet TDT 0.6B v3, its own punctuation0.720
Granite + bert-restore-punctuation (felflare)0.471
Granite alone0.000

Each mark, capitals, and what it costs

F1 per mark and capital accuracy on Granite's transcripts. Changed words is the share of Granite's words the restorer itself altered before the safe transfer put them back. On true words is the same F1 when the restorer is given the reference words, which separates its skill from Granite's errors. Time is the median per request on a shared CPU; memory is what loading it added to the process.

OptionFull stopCommaQuestionCapitalsChanged wordsOn true wordsTimeMemorySize
pcs_en (1-800-BAD-CODE)0.8730.5930.66796.2%0.25%0.79135 ms436 MB200 MB
Local language model (Qwen3.8 27B)0.9130.5640.72397.6%0.85%0.764166 mson the card27.3 GB
Horizon-Labs base, with a casing rule0.8850.5040.65194.4%0.00%0.73731 ms843 MB1.1 GB
Horizon-Labs small, with a casing rule0.8710.5260.52094.4%0.00%0.71823 ms579 MB537 MB
bert-restore-punctuation (felflare)0.5290.3910.65297.1%0.00%0.52219 ms643 MB416 MB

The same clip, punctuated each way

What was said
And also, um, is this informed, um, this plan informed by anything you see in the market, actions by competitors or competitive, um, levels overall in the market?
Granite alone
and also is this informed this plan informed by anything you see in the market actions by competitors or competitive levels overall in the market
Granite + pcs_en (1-800-BAD-CODE)
And also, is this informed this plan informed by anything you see in the market, actions by competitors or competitive levels overall in the market?
Granite + Local language model (Qwen3.8 27B)
And also, is this informed? This plan informed by anything you see in the market actions by competitors or competitive levels overall in the market?
Cohere Transcribe, its own
And also, is this informed, this plan informed by anything you see in the market, actions by competitors or competitive levels overall in the market?
What was said
Between roast beef and potatoes how can we lose?
Granite alone
between roast beef and potatoes how can we lose
Granite + pcs_en (1-800-BAD-CODE)
Between roast beef and potatoes, how can we lose?
Granite + Local language model (Qwen3.8 27B)
Between roast beef and potatoes, how can we lose?
Cohere Transcribe, its own
Between roast beef and potatoes, how can we lose?
  • Granite with pcs_en scores 0.748, more than Parakeet’s own punctuation (0.720) and Qwen3-ASR’s (0.735), and close to Whisper (0.757). It takes 35 ms per request on the CPU, needs no graphics memory, and is one 200 MB ONNX file.
  • The local language model scores a little higher, 0.764, at 166 ms per request, and only when a 27B model is already loaded. Cohere’s own punctuation is the best of all at 0.797, but Cohere needs three times Granite’s graphics memory.
  • Commas are where every option is weakest. Spoken English has no reliable comma, and people disagree about them in the references too.
  • The Horizon-Labs models score 0.728 (base) and 0.722 (small); they cover 88 languages, which matters for Parakeet’s other languages more than for Granite. bert-restore-punctuation, trained on restaurant reviews, scores 0.471.
11Whistle

Whistle: 16.9 MB, and almost three times the errors

Whistle came out on 2 October 2026 from Cactus Compute and was posted to r/LocalLLaMA as speech to text in a 16.9 MB file. It has 55 million parameters, 36 million of them active, stored at 2 to 4 bits, and covers 7 languages under Apache 2.0. It does not run on transcribe.cpp: it is a .cact file for Cactus’s own needle engine, which runs only on the CPU and takes at most 30 seconds of audio per call. The author says a version without that limit is coming.

We ran it the same way as the other five: the same 1,198 clips, the same scorer, English forced, the engine’s defaults, through cactus-needle 3.1.1, engine 3.1.0. The weights and the engine were checked against the publisher’s SHA-256.

Whistle beside GraniteLower is better in every column. Word error rate is the mean over the six test sets, 1,198 clips; Granite Q8_0's was measured on the graphics card, and its CPU rows run the same weights. Memory is what the process holds with the model loaded: system memory on the CPU, graphics memory for the card. Start and load is starting the runtime in a fresh process and loading the file. Request is the same 6.04 s clip with the model loaded. Times are medians of 7 fresh processes for Whistle and five for Granite, on a CPU other work was also using.
ModelFileMBWord error rate%; bar is points above the bestMemory heldMBStart and loadsecondsRequest6 s clip
WhistleCPU, its own engine16.1 MB15.62%77 MB71 ms611 ms
Granite Q8_0CPU, transcribe.cpp482 MB5.86%594 MB609 ms220 ms
Granite Q5_K_Mgraphics card, transcribe.cpp320 MB5.88%978 MB785 ms35 ms
Mean word error rate, every model in the labMean over the six test sets, 1,198 clips. The five transcribe.cpp models at Q8_0 on the graphics card; Whistle on the CPU at its published 2 to 4 bits.
Granite Speech 5.0 470M TurboCTC5.86%
Cohere Transcribe6.25%
Parakeet TDT 0.6B v36.67%
Qwen3-ASR 0.6B7.71%
Whisper large-v3-turbo9.34%
Whistle15.62%

Whistle by test set

Whistle's published figures are on the full test splits; ours are the same 200 clips per set every model here was scored on, with the same normaliser. Its authors published no Common Voice or VoxPopuli figure in English and an AMI figure only for a cleaned version.

ModelLibriSpeech cleanLibriSpeech otherCommon VoiceAMIEarnings-22VoxPopuliMean
Whistle, as published4.31%10.49%n/an/a19.01%n/an/a
Whistle, measured here3.74%10.13%25.48%26.87%18.40%9.07%15.62%
Granite Q5_K_M1.13%2.68%6.70%10.65%8.53%5.57%5.88%
Whisper large-v3-turbo Q8_01.91%3.93%11.22%17.99%10.92%10.09%9.34%
Parakeet TDT 0.6B v3 Q8_01.60%3.36%9.52%9.77%10.39%5.35%6.67%

Whistle's own punctuation

Punctuation F1 and capital accuracy on Common Voice, AMI and Earnings-22 (598 clips), scored the way section 10 scores every option.

OutputAll marksFull stopCommaQuestionCapitals
Whistle, its own0.7520.9190.5540.68297.7%
Granite + pcs_en (1-800-BAD-CODE)0.7480.8730.5930.66796.2%
Cohere Transcribe, its own0.7970.9220.6410.76098.1%
Whisper large-v3-turbo, its own0.7570.8890.5900.76696.9%

The example clips, Granite and Whistle

VoxPopuli11.7 s
What was said
while i respect one country two systems' i find it shocking that a country run by a communist party appears to be advocating a system which gives representation only to those with wealth and privilege.
Granite Speech 5.0 470M TurboCTC1 error
while i respect one country 2 systems i find it shocking that a country run by a communist party appears to be advocating a system which brings representation only to those with wealth and privilege
Whistle3 errors
Mr President, while I respect one country two systems, I find it shocking that a country run by a communist party appears to be advocating a system which will representation only to those with wealth and privilege.
AMI6.1 s
What was said
Yeah well yeah well that has been e that has been eliminated, so that's that's unfortunately a moot point now.
Granite Speech 5.0 470M TurboCTC1 error
well yeah well that has been e that has been eliminated so that is that is unfortunately a moot point now
Whistle7 errors
Yeah, well, yeah, well, that has been eliminated, so that's unfortunately a mute point now.
Common Voice5.1 s
What was said
Born to Russian Jewish immigrants.
Granite Speech 5.0 470M TurboCTC2 errors
born jewish and jewish immigrants
Whistle5 errors
World Division Division in France.
  • Whistle’s published numbers hold up. On LibriSpeech clean it got 3.74% against a published 4.31%, on LibriSpeech other 10.13% against 10.49%, and on Earnings-22 18.40% against 19.01%.
  • It is still far behind Granite. Its mean over the six sets is 15.62%, 2.7 times Granite Q5_K_M’s 5.88% and worse than every model in the lab. The gap is widest on Common Voice (25.48%), where people with many accents read into their own microphones, and on AMI meetings (26.87%), which is the closest test set to someone talking to an agent.
  • Part of the AMI figure is Whistle tidying up: it leaves out repeated words such as “that’s that’s”, which the AMI references keep and the scorer counts as deletions. Words left out are 8.7% of AMI’s words for Whistle against 3.0% for Granite. That does not explain the gap. Words Whistle replaced with a different word are 13.0% on AMI and 19.8% on Common Voice, against 4.5% and 5.3% for Granite.
  • When Whistle mishears, it writes a fluent, punctuated sentence that is wrong, such as “I’m gonna make a little shadow and shadow onto Foster.” for “When the girl improves, Charlotte takes her home to Boston.” Granite got that clip wrong too, as “venical records car takes her home to boston”, which is plainly broken. In a chat box a wrong sentence that reads well is more likely to be sent without being checked.
  • Its own punctuation is good: 0.752 F1, level with Granite plus pcs_en (0.748) and behind only Cohere (0.797).
  • It is small and starts at once: the process holds 77 MB with the model loaded, about 35 MB of it Python, and is ready 71 ms after the process starts. Granite Q8_0 on the CPU holds 594 MB and is ready in 609 ms.
  • It is not faster. A six second request takes 611 ms with Whistle loaded, against 220 ms for Granite on the same CPU and 35 ms for Granite on the graphics card. Whistle’s decoder writes one token at a time with five beams; Granite’s CTC head writes the whole transcript in one pass.
12Recommendation

Ship Granite Speech 5.0 470M TurboCTC at five bits, with pcs_en for punctuation

  • Use Granite Speech 5.0 470M TurboCTC for English, at Q5_K_M. It made the fewest errors of the five (5.88% at Q5_K_M, the same as at Q8_0), needs the least graphics memory (978 MB at peak) and is the fastest. Its file is 320 MB.
  • Add punctuation with pcs_en, through the safe transfer that copies only marks and capitals back onto Granite’s words: 0.748 punctuation F1, 35 ms on the CPU, no graphics memory.
  • Offer Parakeet TDT 0.6B v3 at Q8_0 for the other 24 European languages: 6.67% of words wrong, 1.38 GB at peak, and it punctuates by itself.
  • On a card that is nearly full, Q3_K_M (201 MB) still gets 6.25%, but it needs a patched transcribe.cpp; Q4_K_M (6.09%) is the smallest file that runs on the release.
  • Embed transcribe.cpp through its Rust bindings. Set TRANSCRIBE_NO_FLASH=1 when running Parakeet or Cohere on CUDA.
  • Load the model when the button is pressed, in a helper process started with CUDA_VISIBLE_DEVICES set to one card. Run one second of silence through it while the person is still talking. Keep the process for 5 minutes after the last press, then end it so the card gets back everything, including the CUDA context.
  • Do not ship Whisper large-v3-turbo for chat: it replaced 20 of the clips with “Thank you.”.
  • Do not ship Whistle for agent chat. It needs the least memory, but it gets 15.62% of words wrong against Granite’s 5.88%, and Granite on the CPU alone is faster per request. Whistle is for devices with tens of megabytes to spare, not for a desktop.
13Method

How it was measured

  • Machine: NVIDIA GeForce RTX 5090 (driver 580.97), Intel(R) Core(TM) Ultra 9 285, 127 GB of memory, Windows 11 10.0.26100, transcribe.cpp 0.3.1. Only one graphics card was used.
  • Every run was a fresh process. Graphics memory comes from Windows’ per process counter (GPU Process Memory, Dedicated Usage), sampled every 50 ms, which counts only the model’s own process. A first attempt read the whole card from NVML instead, and other programs allocating on the same card made those readings useless; they are kept in the raw results but not used.
  • The machine was shared with other work while these numbers were taken. Each run recorded how much of the CPU other processes used and which other tickets were in progress. Load and latency figures are medians of five fresh processes; the range is in the data file.
  • Word error rate: the reference and the transcript both go through the Whisper English normaliser used by the Open ASR Leaderboard, then jiwer counts substitutions, deletions and insertions. The mean is the average of the six test sets. Our six sets differ from the leaderboard’s eight, so our means are not directly comparable to the published ones; LibriSpeech clean, which both use, is compared in the table below.
  • Two Common Voice clips shared an id with another clip and were dropped, leaving 198 in that set.
  • Cold start: the operating system’s file cache could not be emptied without administrator rights, so the cost of reading a model from the drive was measured as an unbuffered read of the same file.
  • Smaller Granite files: Q5_1, Q5_0, Q4_1 and Q4_0 were made with transcribe.cpp 0.3.1’s transcribe-quantize from the published F16 file. Q3_K_M, Q3_K_S and Q2_K needed presets added to that tool and Q3_K and Q2_K added to the loader’s allowed weight types (TRANSCRIBE_QUANT_LINEAR_TYPES) in a local CUDA build for this card only.
  • Whistle ran through cactus-needle 3.1.1 and the needle engine 3.1.0 (libneedle3.dll) in its own Python environment, on the CPU pinned to the eight performance cores, with the package’s anonymous usage reporting turned off. Its accuracy run took 550 seconds for 129 minutes of audio, 14.04 times real time, on a CPU other work was using. Its load figures are medians of 7 fresh processes. Granite’s CPU figures beside it are the five CPU load runs from the first round of this lab; Granite’s word error rate on the CPU was not measured separately.
  • Punctuation ran on the CPU in its own Python environment (onnxruntime, transformers with CPU torch); the language model ran where it already lives, NInfer on the second graphics card, with thinking off and temperature 0.
  • The code is in ai-service/tools/stt-lab: download and hash check, test audio, the benchmarks, the scorer, the keep loaded replay, the punctuation runner and scorer, the Whistle runner, and the script that writes this page’s data.

Our numbers against the leaderboard's

LibriSpeech test clean is in both our test sets and the leaderboard's, so it checks the harness: every model lands within half a point of its published figure. The leaderboard's eight set average is beside it; its sets differ from our six.

ModelOurs, LibriSpeech cleanLeaderboard, LibriSpeech cleanOurs, mean of six setsLeaderboard, mean of eight sets
Parakeet TDT 0.6B v31.60%1.52%6.67%4.86%
Cohere Transcribe1.03%0.97%6.25%4.67%
Qwen3-ASR 0.6B1.75%1.70%7.71%5.05%
Whisper large-v3-turbo1.91%2.13%9.34%6.36%
Granite Speech 5.0 470M TurboCTC1.08%1.48%5.86%5.03%

The test audio

200 clips from each test set of the Open ASR Leaderboard, picked with a fixed seed; clips over 30 seconds or with an empty reference were skipped.

SetWhat it isClipsMinutes
LibriSpeech cleanaudiobooks read aloud, clear recordings20023.8
LibriSpeech otheraudiobooks with harder speakers and recordings20021.7
Common Voicevolunteers reading a sentence into their own microphone, many accents19819.7
AMImeetings recorded by a headset microphone, spontaneous speech2007.9
Earnings-22company earnings calls, accented speech, names and figures20024.9
VoxPopuliEuropean Parliament speeches20030.8