Understanding local speech recognition

How much can you trust a local transcript?

We compared four speech-to-text engines on English and Italian recordings. Along the way, we looked at what their scores mean, why they make different mistakes, and how to choose one for your own audio.

One of the recordings we tested contains “I couldn’t do this one.” Phonon returned “I can do this one.” The transcript reads smoothly, but it changes what the speaker meant.

That is an awkward problem if you’re choosing a transcription model. You want a useful way to compare them, but a score cannot tell you whether the word a model missed was “um,” someone’s surname, or the “not” in a decision.

We build MeetingStow, which transcribes meetings on your Mac. We wanted to compare the four engines in the app: Apple SpeechAnalyzer, Qwen3-ASR, Phonon-2, and Parakeet Ultra. Ultra made the fewest word errors in our test, while Apple took the least time. Looking through the actual transcripts helped us understand what those results did and didn’t tell us.

The comparison uses 26 public clips: six English meeting excerpts and twenty Italian recordings of people reading sentences. That is enough to find useful examples and check our implementation, but it is a small sample. We’ll explain the terms first, then walk through the results. If you’d rather inspect the outputs yourself, the recordings’ references, transcripts, scores, and reproduction tools are available below.

Is speech-to-text the same thing as TTS?

It’s easy to mix up the names. Speech-to-text, or STT, takes audio and produces written words. You’ll also see it called automatic speech recognition, or ASR. Text-to-speech, or TTS, starts with written words and generates a spoken voice. A transcription app uses the first; a tool that reads an article aloud uses the second.

This article measures speech-to-text. If you’re choosing a TTS voice, you’ll want to listen for pronunciation, natural pacing, and how it handles names and numbers, as well as how quickly speech starts. Our transcription scores don’t measure those things. Apple has separate APIs for the two jobs: SpeechAnalyzer for recognition and AVSpeechSynthesizer for speaking text.

What happens between recording a call and reading the notes?

Recognizing the words is only one part of making a transcript you can use. These are the other terms you’ll encounter in the comparison:

Voice activity detection
Usually shortened to VAD. It estimates which parts of a recording contain speech. An app can use that information to skip silence or choose where to split the audio. A poorly placed cut can lose part of a word.
Diarization
Works out who spoke when, usually with labels such as “Speaker 1” and “Speaker 2.” It doesn’t, by itself, tell you a person’s name. Recognizing someone from a saved voice profile is a separate task.
Alignment
Places recognized words on the audio timeline. That gives you timestamps you can use to replay a sentence. A transcript can have the right words and still send you to the wrong point in the recording.
Summarization
Turns the transcript into shorter notes, decisions, or action items. It is a separate model task. We didn’t score recaps here, so a good transcription result is not a measurement of summary quality.

You can therefore get several different things wrong: the words, the speaker labels, the timestamps, or the summary. If you need to verify a client’s deadline, having the right words attached to a useful timestamp matters more than a tidy paragraph.

Why can two apps using the same model behave differently?

The model contains learned patterns for recognizing speech, stored as numerical weights. The runtime is the software that runs the model. The app also decides how to prepare the audio, split it into chunks, and assemble the results. When we say “engine” below, we mean that implemented recognition path, not just a model name.

You’ll see labels such as FP16 and Q8_0 in the method table. FP16 uses 16-bit floating-point numbers; Q8_0 is an 8-bit quantization format. These describe how model weights are stored. Those choices can affect memory, speed, and output. Comparing the versions an app actually uses is more informative than assuming every implementation of a model behaves alike.

“Local” means the recording is processed on the device rather than sent to a remote service for recognition. The model may still need an initial download. It doesn’t tell you whether recognition is accurate, whether the app is fast on your hardware, or whether a backup service copies the resulting files.

What did we compare?

We ran the four engines on an Apple M2 Max with 64 GB RAM, running macOS 26.5.2. The app was a signed Debug build of MeetingStow 0.5.27 (build 35), with its native MLX package optimized. We used the app’s transcription methods so that audio preparation and transcript assembly would be included in the comparison.

Will these engines run on my Mac?

System requirements: MeetingStow requires an Apple Silicon Mac and macOS 15 or newer for recording, local transcription, and local recaps. The optional Apple Speech engine tested here uses SpeechAnalyzer and SpeechTranscriber, which require macOS 26 or newer. Apple-powered recaps also require macOS 26 or newer with Apple Intelligence enabled. These benchmark results were measured on macOS 26.5.2; they do not validate performance or compatibility on macOS 15.

The four implementations measured on October 19
EngineRuntime / checkpointProcessing included
AppleSpeechAnalyzer / SpeechTranscriberNative recognition. Separate from Apple Intelligence recaps.
QwenQwen3-ASR 1.7B · Q8_0 · transcribe.cppApple evidence, speech windows, recognition, and transcript assembly.
PhononPhonon-2 · native Swift MLXThe app’s audio preparation, windowing, recognition, and assembly.
UltraParakeet Ultra · FP16 · native Swift MLXThe same native wrapper as Phonon, with the Ultra checkpoint.
Which version of Parakeet Ultra did we use?

Parakeet Ultra is Moondream’s post-trained version of NVIDIA’s Parakeet TDT 0.6B v3. We use the FP16 MLX conversion, pinned to revision 5acd3970b21853434afd56ed0c8f84a08a52cae8. The conversion omits the upstream VAD head. These are measurements of our Swift implementation on a Mac, not the upstream GPU runtime or published TensorRT results.

English / Conversation

AMI meeting corpus

Six 60-second mixed-headset excerpts from ES2004a and ES2004b, starting at 60, 240, and 480 seconds. Human word annotations from all speakers are ordered by word start time.

360s · 775 normalized words
Italian / Read speech

Google FLEURS

The first twenty Italian test rows in converted dataset order. Some sentence content repeats. These are people reading sentences, not an Italian conversation.

275.16s · 493 normalized words

We computed speaker intervals once for each clip and supplied the same intervals to every engine. None received the reference words, a list of names, or vocabulary hints. We checked the audio files against the original fixture hashes so every run used the same recordings. See the AMI documentation and FLEURS dataset card for the source recordings’ scope.

How did we run and time the tests?

Word error rate (WER) = (substitutions + deletions + insertions) ÷ reference words. We sum counts across clips before dividing. English uses Whisper’s English normalizer. Italian normalizes Unicode, case, punctuation, and whitespace, retaining apostrophes and numeric spelling.

Engines ran sequentially in this order: Apple, Phonon, Ultra, Qwen. Each received one warmup per language, then two measured passes per clip. Displayed time is the sum of each clip’s median of those passes.

Transcription time includes audio export, resampling, segmentation, recognition, and transcript assembly. Qwen includes its Apple evidence pass. Downloads, model preparation, warmups, shared diarization, saving, voiceprint matching, and recaps are excluded. Diarization groups speech by anonymous speaker; it is timed once per fixture and shown separately below.

Two repeats show short-run consistency, not statistical confidence. Fixed order, background load, caches, and thermals can affect speed. Speaker-label quality, timestamp accuracy, peak memory, energy, and cold-start latency were not scored.

What does a word error rate of 13.94% mean?

Word error rate, or WER, counts three kinds of mistake: substituting one word for another, leaving a word out, or adding a word that wasn’t in the reference. Add those errors and divide by the number of words in the human reference. For example, one substitution and one missing word in a ten-word reference give a WER of 20%.

Lower is better, but the percentage isn’t a count of sentences understood correctly. It doesn’t say how serious the errors were, and it can exceed 100% if the model adds enough words. Our English result for Ultra is 108 errors across 775 reference words, which gives 13.94%.

Here are the four engines under the same scoring rules. Use the language buttons to switch samples; the timings are for processing all the clips after warmup.

Explore the measured results

6 meeting excerpts · 360 seconds · 775 reference words

WER ↓ lower is betterWarm transcription · excludes diarization
English: Apple SpeechAnalyzer 17.42%, Qwen3-ASR 1.7B 16.00%, Phonon-2 14.84%, Parakeet Ultra 13.94%; Italian: Apple SpeechAnalyzer 4.87%, Qwen3-ASR 1.7B 2.23%, Phonon-2 11.97%, Parakeet Ultra 1.62%
Figure 1. All four native engines, the same verified clips and scoring rules. Each language has a zero-to-twenty-percent axis. The speech conditions differ between languages. PNG · SVG
October 19 native run · time excludes shared speaker analysis
SampleEngineWER ↓Word errors ↓Warm time ↓
English
775 words
Apple SpeechAnalyzer17.42%1354.32s
Qwen3-ASR 1.7B16.00%12419.48s
Phonon-214.84%1156.30s
Parakeet Ultra13.94%1084.99s
Italian
493 words
Apple SpeechAnalyzer4.87%242.93s
Qwen3-ASR 1.7B2.23%1117.73s
Phonon-211.97%596.53s
Parakeet Ultra1.62%84.95s

In English, Ultra makes 108 errors out of 775 words, seven fewer than Phonon and sixteen fewer than Qwen. Its lead over Phonon is only 0.90 percentage points. Dropping one English clip at a time leaves Ultra with the lowest aggregate WER in 5 of six subsets. That tests sensitivity to these clips; it does not make six excerpts representative of meetings in general.

In Italian, Ultra makes 8 errors out of 493 words, compared with Qwen’s 11. Three errors separate them. English conversation and Italian read speech are different tasks: the lower Italian percentages do not establish that any engine is “better at Italian.”

How long would you actually wait for the transcript?

The transcription stage is quick on this machine: Ultra takes 4.99 seconds for the six minutes of English audio, and Apple takes 4.32 seconds. But we also spent 5.34 seconds separating the speakers. Adding that stage brings Ultra’s total to 10.33 seconds, before saving or creating a recap. Once recognition is this fast, work elsewhere in the app becomes a noticeable part of the wait.

English: Apple SpeechAnalyzer 9.67s, Qwen3-ASR 1.7B 24.83s, Phonon-2 11.64s, Parakeet Ultra 10.33s; Italian: Apple SpeechAnalyzer 7.48s, Qwen3-ASR 1.7B 22.29s, Phonon-2 11.09s, Parakeet Ultra 9.51s
Figure 2. Shared diarization adds 5.34s for English and 4.55s for Italian to every engine. Qwen’s Apple evidence time is separated from its other processing. PNG · SVG

These are warm runs: the model is already loaded and has processed a clip in each language. A cold start would include loading and initialization; a first-time setup may also include downloading model files. We haven’t combined those into a startup benchmark. And processing a finished recording faster than its duration doesn’t tell you how soon live captions would appear while someone is speaking.

We made two measured passes per clip. Every repeated word-error count matched, although one Apple Italian name changed spelling without changing the score. Both outputs and their timings are in the download. Two passes are useful as a consistency check, but they don’t tell us how speed varies over many runs.

What does a word error sound like?

The counts become more useful when you listen to the recording beside the output. Here is the sentence from the opening, with its surrounding words. Phonon changes the negation; the other three engines preserve it.

English · ES2004b_240_300Negation reversed
Human reference

“I ran out of time so I couldn’t do this one as fun as the last one”

Phonon

“I ran out of time so I can do this one as fun as the last one”

Apple + Qwen + Ultra

All three preserve “couldn’t” in this sentence.

Original 60-second benchmark excerpt. AMI Consortium / University of Edinburgh, CC BY 4.0; extracted from ES2004b mixed-headset audio.

If you were writing notes from the Phonon version, you could come away with a different understanding of what the speaker could do. We didn’t run this through a summarizer, so we can’t say how a recap model would handle it. The transcription error is already enough to warrant checking the audio.

Italian · FLEURS 1883, row 1A date loses a digit
Human reference

“…l’apertura al traffico è avvenuta solo nel marzo 2017”

Phonon

“…l’apertura al traffico è avvenuta solo nel marzo207”

Apple + Qwen + Ultra

All three preserve “marzo 2017”. Apple also outputs “avvenutauta” elsewhere in the sentence.

Original FLEURS recording, Google, CC BY 4.0. The quoted reference means that traffic opened only in March 2017.

The same Italian sentence contains a harmless style difference: the reference writes 15 metri, while Phonon writes quindici metri. Both mean “fifteen meters.” That deserves different treatment from changing 2017 into 207.

Names · Italian FLEURS 1669, row 10

SourceName spelling
Human referenceChandra Shekhar Solanki
Apple, first passChandra Sekar Solki
PhononChandra Secker Solanki
QwenChandra Sekhar Solanki
UltraChandra Sekar Swanky

Spelling variants can inflate WER, but shortened or wrong names also make searching and linking people harder. Ultra has the lowest aggregate WER, but Qwen is closest on this name; none matches the reference spelling exactly. We did not measure whether providing known names would fix this case.

Missing, changed, and added words for all four engines. English errors are predominantly missing words; Italian errors are predominantly changed words.
Figure 3. Missing words dominate the English score. Ordering overlapping speakers into one reference sequence is a difficult target for a mixed audio track; these counts do not establish which omissions came from overlap. PNG · SVG

Other production problems remain outside this test: clipping, quiet microphones, music, long silence, echo, and sentences that switch languages. Plausible but unsupported text is also a failure to investigate. We did not run a silence or hallucination stress test, so this article assigns no hallucination rate to any engine.

Why can the same model get a different score?

Should “fifteen” and “15” count as different words?

We rescored Italian with the same limited rules on both sides: split letter–digit boundaries, expand integer digits to Italian cardinal words, and expand numeric m to metri. They forgive 15 metri versus quindici metri, but not a change from 2017 to 207.

Original and formatting-aware Italian word error rates for Apple, Qwen, Phonon, and Ultra. The ordering is unchanged.
Figure 4. Post-hoc sensitivity analysis of the saved outputs, with identical rules for each reference and hypothesis. These rules do not implement complete Italian number normalization. PNG · SVG

Apple falls from 24 to 23 errors, Qwen from 11 to 10, and Phonon from 59 to 51. Ultra stays at 8. Formatting explains some errors, but it does not change the ordering on these recordings.

What happens if Qwen runs without Apple’s help?

Our Qwen path uses Apple evidence to influence speech windows and text decisions, as well as to place text on the timeline. We reran Qwen on all 26 clips with that evidence disabled, using the app’s voice-activity-based fallback. This changes several pipeline decisions together, so it cannot isolate the effect of alignment alone.

English: Apple-assisted Qwen 16.00%, 19.48s; without Apple evidence 14.97%, 18.41s. Italian: Apple-assisted 2.23%, 17.73s; without evidence 2.84%, 16.87s.
Figure 5. Same build, audio hashes, scorer, and two warm passes. The alternative ran afterward in a separate process, so speed differences remain directional. Shared diarization is excluded. PNG · SVG

Without Apple evidence, English changes from 124 to 116 errors; Italian changes from 11 to 14. The same pipeline change helps one sample and hurts the other.

That is why we’ve described the implementation alongside the model name. Giving Qwen the same recording with a different set of speech windows and correction rules changes its output, even though the underlying model is the same.

We would need word, timestamp, and speaker-label evaluations together before using this result to change Apple assistance in production. A better word count alone cannot settle that choice.

Which model should you try?

If your recordings resemble these samples, we’d start with Parakeet Ultra. It made seven fewer English errors than Phonon and three fewer Italian errors than Qwen. It also preserved the negation and date shown above. Those are reasons to try it on your own recordings, rather than evidence that it will always be best.

Apple is worth trying if you want a draft quickly and have macOS 26. It finished first in both samples, with more word errors. Whether that tradeoff is acceptable depends on what you’re doing with the text. Searching a recording for a topic and sending a client a written commitment demand different levels of checking.

We’d compare a few recordings that contain the things you need the model to get right: your colleagues’ names, technical terms, accents, or people talking over one another. Listen to the unclear passages and check the output. Include the time you spend correcting it when you decide whether a model is fast enough for your work.

We haven’t included Whisper, cloud services, or every other local model. These are the four engines already integrated into MeetingStow. The results help us choose among those implementations; they don’t settle the wider market.

What do we still need to test?

The next useful step is more conversation audio, particularly Italian meetings, with longer recordings and a wider range of speakers. We also need separate checks of speaker labels and timestamps. The current mixed-audio fixtures don’t include speaker-label ground truth or separate microphone tracks, so they can’t validate those parts of the app or its recent microphone-filtering changes.

MeetingStow has used Parakeet Ultra by default for new installs since version 0.5.25, while preserving existing engine and language preferences. This comparison checks that choice against a fixed set of clips. It also gives us recordings to return to when the app changes, so we can check whether an apparent improvement actually kept the words we care about.

Can you check the results yourself?

The JSON includes human references, both outputs per engine, per-clip error counts and timings, audio hashes, and the supplementary analyses. The CSV contains aggregate scores. Every figure is available as SVG and PNG, and the PDF contains this version of the article.

If you want to rescore the saved transcripts, download the JSON and Python analysis above. You don’t need to load any speech models for that. To make new measurements through the app, the repository workflow is:

python app/Benchmarks/Transcription/benchmark.py prepare \
  --output app/.benchmark-data/transcription --italian-count 20
app/scripts/build-app.sh debug
MEETINGSTOW_RUN_TRANSCRIPTION_BENCHMARK="$PWD/app/.benchmark-data/transcription/fixtures.json" \
MEETINGSTOW_TRANSCRIPTION_BENCHMARK_OUTPUT="$PWD/app/.benchmark-data/transcription/native.json" \
  "app/.build/MeetingStow Dev.app/Contents/MacOS/MeetingStowNative"
python app/Benchmarks/Transcription/benchmark.py score \
  app/.benchmark-data/transcription/native.json --expected-engine-count 4 \
  --hardware-label 'Apple M2 Max' --output /tmp/native-results.json

The repository’s app/Benchmarks/Transcription/README.md has dependency setup and the Qwen alternative command. You can also download the standalone analysis to rescore the published outputs and recreate the charts without running a recognizer or accessing our repository. Build and run provenance records the binary and source hashes.

What are the limits of this comparison?

Six English clips come from two related scenario meetings. Twenty Italian clips are read speech, including repeated sentence content. Public recordings may have appeared in training data; overlap was not established. Mixed-speaker reference ordering, clipped words, and normalizer choices influence scores. We make no confidence-interval, significance, or population-wide claim.

The scorer uses jiwer 4.0.0 and transformers 5.17.0; formatting uses num2words 0.5.14; figures use matplotlib 3.10.8. This is a signed Debug app with an optimized MLX package, not a cross-device or Release-build performance study. Two warm repetitions do not characterize tail latency, and we did not measure battery use, peak RAM, or a representative first-use experience.

The measurements were collected on October 19 with MeetingStow 0.5.27. The earlier October 5 article covered three engines. This revision adds explanations; it uses the same saved outputs and scores.

Dataset attribution. English audio and references: AMI Consortium / University of Edinburgh, via the FluidInference AMI mirror and AMI 1.6.2 annotations. Italian audio and references: Google FLEURS, Conneau et al. Dataset material is credited under CC BY 4.0. The English player is an extracted excerpt; the Italian player retains the selected recording. Transcript highlights and scores are our analysis.