Choose Pocket C++ with mixed precision and a short Alba reference.
The current English model now clears the proposed CPU voice gates in a working benchmark: 94 ms median audible output across 42 expanded utterances, 283 ms worst, 499 MiB peak RSS, 57 ms cancellation and 2.6% transcription WER. Kitten Nano FP32 remains the fallback.
5 September 2026 Native C++ / ONNX Runtime Current English checkpoint
The choice
Recommended:english_2026-04, the optimized stephvax ONNX export, PocketTTS.cpp with the recorded compatibility patch, INT8 language model plus FP32 flow/decoder, temperature 0.3, one flow step, two CPU threads, first chunk one frame and later chunks capped at three frames. Use the first three seconds of Kyutai’s actual Alba casual recording, resampled to 24 kHz, and the bounded leading-silence filter described below.
The original three-prompt corpus scored 6.2% WER across three seeds (276 words), still below the proposed 7% ceiling. The expanded Alba run covered 14 prompts and three seeds, 504 reference words. It had 13 ASR word errors (2.6%); “Done.”, “No.”, “Stopping.” and the disconnection response were retained on every draw. One correction was transcribed as “the test passed, but the bill failed,” and the long single sentence lost words on two draws. These samples need listening review. Kitten had zero ASR errors on the same corpus, so Pocket wins the latency/memory trade, not every quality measure.
Prepared Expresso is a second usable Pocket voice: 165 ms median across the expanded prompts, 430 MiB peak, 69 ms standard cancellation and 2.4% WER, but its worst prompt reached 380 ms. Its one-time voice preparation peaked at 938 MiB; later fresh-runtime runs reused prepared state and stayed around 439 MiB. Prefer the shorter Alba reference to avoid that preparation spike.
Keep Kitten Nano FP32 as the fallback. On the expanded corpus it reached a 557 ms overall median, 730 ms on the standard reply, 4,193 ms worst, 541 MiB peak and 678 ms standard cancellation. Its latest-trigger cancellation took 1,983 ms. It offers better measured transcription accuracy here, but a much weaker interactive response.
This is the best measured Linux CPU configuration in this investigation. It is a working native benchmark candidate, not a finished production integration or a cross-platform release. No installed Jarvis provider was switched.
Earlier Kokoro, Sherpa, Kitten and Piper results remain available. This investigation supersedes the earlier “keep Kokoro” architecture recommendation; it does not change the installed application.
Measured results
Milliseconds unless marked otherwise. Warm is the median 25-word prompt. Worst audible covers every warm prompt in that run. Cancel is request-to-synthesis-return after the 250 ms trigger; worst cancel covers 25, 250 and 1,000 ms triggers. RSS is MiB. Destroy / trim distinguishes runtime destruction from explicit allocator trimming. Gap is total simulated underrun over all warm outputs. WER is Parakeet transcription error, not a listening score.
Historical Kitten Nano FP32: 725 ms warm, 745 ms cancellation, 433 MiB peak, 2.2% WER over 92 words. The new Kitten row above uses the expanded prompts and a fresh run. Model, speaker, text and hardware affect every number; do not treat author benchmarks on other machines as comparable measurements.
What changed the outcome
Measure speech, not the first buffer
C++ produced its first buffer in roughly 26 ms, but the Loona output often began with 590–970 ms of near-silence. A bounded streaming filter waits for a 10 ms window at −50 dBFS and retains 40 ms before it. It removes only the leading prefix, stops removing after two seconds, and preserves every later pause. The −60 dBFS attempt opened on a faint decoder transient and did not help.
Use the current model contract
The runtime needs the English bundle’s learned BOS voice vector and no legacy space padding for short text. Mixed precision uses INT8 language-model weights and FP32 flow/decoder. The optimized export uses compact FP16 circular KV state. The C++ source was adapted explicitly; these are not measurements of an untouched upstream binary.
Bound streaming chunks
Three-frame chunks produced much faster cancellation than the 15-frame setting. Generation, decoder output, emitted PCM and completed worker shutdown are different events; cancellation was timed through the final thread join.
Choose and prepare the voice
The short Loona reference met latency and memory targets but exceeded the quality target on the shared long paragraph. Reference identity was corrected during this study: initial files labelled “alba” actually used Expresso. The report labels them accurately. Actual Alba uses alba-mackenna/casual.wav. A prepared fixed voice avoids re-encoding a long reference on every fresh runtime.
Listen to the candidates
These are generated artifacts, not recorded speaker output. Compare the voice, consonants, sentence ends, and the meaning of the correction prompt. Automated transcription cannot decide naturalness or personal preference.
C++ mixed, Alba 3 s, onset filter: short
C++ mixed, Alba 3 s, onset filter: typical
C++ mixed, Alba 3 s, expanded prompts: short
C++ mixed, Alba 3 s, expanded prompts: typical
C++ mixed, Alba 3 s, expanded prompts: correction
C++ mixed, prepared Expresso, expanded prompts: short
C++ mixed, prepared Expresso, expanded prompts: typical
C++ mixed, prepared Expresso, expanded prompts: correction
Kitten Nano FP32, expanded prompts: short
Kitten Nano FP32, expanded prompts: typical
Kitten Nano FP32, expanded prompts: correction
Scope and reproducibility
Each configuration ran in a separate process, CPU affinity 0,2, with a two-thread inference budget. Heavy inference and builds ran sequentially. Pocket used english_2026-04, temperature 0.3, one flow step. C++ ONNX Runtime was 1.23.2; Kevin Python/ORT used 1.24.4, CPU execution, two intra-op threads and disabled spin waiting. This measures whole runtime configurations, not an isolated language-only performance comparison.
The original prompts contain 92 words; each three-draw quality result covers 276 words. The expanded corpus adds one-word responses, numbers, task ambiguity, disconnection, negation, contractions and a long single sentence. Each draw uses a different seed. NumPy and C++ random generators differ, so numeric seeds do not establish identical latent noise. Parakeet receives resampled 16 kHz PCM and no hotwords. It can misrecognize correct speech; every transcript is downloadable.
RSS includes the Python/NumPy measurement host. C++ inference itself needs no Python. Disk state is disabled in uncached rows; prepared-voice rows explicitly reuse model-specific state created by the preparation run. The library remains loaded after model destruction. Full worker exit would release its entire address space, but that was not substituted for the reported destruction measurements.
No microphone, speaker/DAC, OS permissions, desktop hotkey, mobile runtime, or other machine was tested. These are Linux CPU measurements. The 24-layer English checkpoint, Rust/Candle, XN and Apple MLX were not benchmarked here; no claim of a universal fastest model is made. The current compact English model and two ONNX runtimes address the concrete unresolved choice from the earlier review.
The C++ API needs a bounded output queue, explicit stream-error propagation, safe exclusive use of each runtime, and cancellation independent of the next audio read. Its current callback queue is unbounded and exceptions are printed rather than delivered as typed failures. The C++ sentence splitter also needs the bundle’s token bound for unrestricted text. These are production integration requirements, even if the measured prompts pass.
Integrate behind the existing Pipecat TTS service and preserve the ordinary voice lifecycle: Full and Controller own speech, Headless remains idle, disabling voice releases the worker, and cancellation discards buffered playback. Keep Kitten Nano FP32 as the fallback choice if native packaging or target-machine acceptance fails. Do not extend the Sherpa Pocket prototype.