Repository navigation
feat(voice): an accurate mode with a Parakeet pass on each pause - #83
Merged
Merged
Conversation
ANT1OFF
force-pushed
the
feat/voice-accuracy
branch
from
November 2, 2026 07:31
e70509b to
af695f9
Compare
ANT1OFF
added a commit
that referenced
this pull request
Nov 2, 2026
Desktop release metadata proposal only. Merging this PR does not publish or tag Gram; follow docs/RELEASING.md to release. --- ## [1.4.0](v1.3.1...v1.4.0) (2026-11-02) ### Features * **agents:** identify Gram's Claude processes as the gram entrypoint ([#91](#91)) ([f7dd703](f7dd703)) * **desktop:** run on Linux ([#82](#82)) ([1d37deb](1d37deb)) * **desktop:** turn voice input off on Linux with one check ([#79](#79)) ([470ff8b](470ff8b)) * **orchestration:** a person's PR comment wakes the worker that owns it ([#86](#86)) ([19bdc1c](19bdc1c)) * **orchestration:** a wrap-up turn when a worker stops without reporting ([#88](#88)) ([36a07fb](36a07fb)) * **orchestration:** workers say what they ruled out and check before repeating ([#90](#90)) ([8bdce01](8bdce01)) * **release:** publish and update Linux AppImage and .deb ([#95](#95)) ([c33c464](c33c464)) * **voice:** an accurate mode with a Parakeet pass on each pause ([#83](#83)) ([2b04a52](2b04a52)) * **voice:** hold one key to talk, with a tone at each end ([#87](#87)) ([1a9b3ef](1a9b3ef)) * **voice:** start capture at the press, and an opt-in ready microphone ([#81](#81)) ([505d240](505d240)) * **web:** a Done section that keeps the last 7 days ([#65](#65)) ([8c7bd49](8c7bd49)) * **web:** Done lists every finished chat ([#67](#67)) ([c91d9ac](c91d9ac)) * **web:** one attention count, quieter rows, a sidebar and board that agree ([#92](#92)) ([f193da4](f193da4)) * **web:** orchestrator → workers in the sidebar, a board that matches ([#80](#80)) ([686e737](686e737)) ### Bug Fixes * **desktop:** harden the Linux key vault and autostart entry ([#85](#85)) ([4b35eac](4b35eac)) * **e2e:** hold the t-flaky turn while the smoke test reads its opening line ([#93](#93)) ([2edc4ac](2edc4ac)) * **e2e:** release the dictation tap as soon as a word is heard ([#94](#94)) ([7781194](7781194)) * prepare only approved local-check sources ([#32](#32)) ([af3fab7](af3fab7)) * repair main after [#32](#32) ([#68](#68)) ([ce352e6](ce352e6)) * **voice:** keep the last word after release ([#78](#78)) ([cc40a47](cc40a47)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: gram-release-please[bot] <351321620+gram-release-please[bot]@users.noreply.github.com> Co-authored-by: Johan <32440065+ANT1OFF@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds an Accurate voice-input mode. Nemotron still streams the live words at the caret. At each 1.2 s pause, and on stop, the speech process trims the utterance's audio with Silero VAD v5 and runs Parakeet TDT 0.6B v2 (int8, sherpa-onnx
OfflineRecognizer) over it. It then commits that text, with punctuation and capitals, in place of the streamed words. Live is the old behaviour. Accurate is the default.Measurements
Apple M5 Pro (18 cores, 24 GB), sherpa-onnx 2.0.0 CPU, 2 threads, run in Node 26 through the same addon the app loads. Other checkouts were running on this machine (load average 10–40), so the timings are pessimistic.
The study's WAVs aren't in the tree, so I used two corpora:
hf-internal-testing/librispeech_asr_dummy, 73 clips, 481 s.say, 20 developer-prompt sentences × 4 voices, 375 s.Neither is the user's voice or microphone. WER is case- and punctuation-insensitive.
say(1216 words)Both models resident in one process: 3.0–3.1 GB steady footprint, 3.38 GB peak; Nemotron alone is ~1.7 GB steady.
Threads for the pass: 1 thread p50 734 ms; 2 threads 203–240 ms; 4 threads 218 ms; 6 threads 310 ms. So it uses 2.
CoreML (
provider: "coreml"): p50 2016 ms, p95 4749 ms, 12.7 s load, 3.3 GB peak, same WER. Rejected.Silero VAD v5, real-time factor 0.008. On LibriSpeech clips with 0.5 s / 1.2 s of −60 dBFS noise around them:
Digital silence and white noise at −60…−20 dBFS gave no text from either model, so the "thank you" hallucination did not reproduce with stationary noise. The VAD skip guards against it anyway.
Design
service.tskeeps each utterance's audio, including the 300 ms lead and the stop tail. On an endpoint or stop it:planClip: keeps 250 ms around the VAD's speech, and returns nothing when no speech was found;decodeAsync, off the main thread, so a cancel still lands;final.release.verified.json, never from the page.accurate passline carriesaudioMs,msandfellBackonly, never text. A test asserts this.SpeechOpenRequest.mode, and amodeargument onDesktopSpeech.prewarm;voice.modein settings (speechModeOf, Accurate by default);SpeechStatus.totalMemoryBytes;SpeechRecognizeris now a union withsherpa-onnx-offline-transducerandsherpa-onnx-silero-vad;SpeechModelSource.url.finalalready replaces the partial; its doc now says the text can differ from the last partial.Why Accurate is the default
Parakeet halves the word errors on real speech (6.43 → 3.04 %) and adds punctuation. On an idle machine it costs about a quarter of a second after each pause. Accurate is offered only with consent, and it degrades to Live when its models are missing, too slow or broken. Machines under 16 GB see only the Live download on the first-run consent screen, because both models together take about 3 GB.
Models and consent
parakeet-tdt-0.6b-v2-en-int8(csukuangfj @1ab9323…, 661 MB, fromnvidia/parakeet-tdt-0.6b-v2@ae9ad07…) andsilero-vad-v5(csukuangfj/vad@fba88cd…, 2.3 MB). Each file has a pinned size and the sha256 that Hugging Face's LFS serves; the Silero file's sha256 also equals upstreamfiles/silero_vad.onnxat tag v5.0.packages/shell/src/modules/speech/MODEL-NOTICES.md(with the full Silero MIT text) is now a kept notice intools/notices. A test fails if any pinned model's attribution or licence URL is missing from it.Screenshots (mock shell)
Checks
bun run typecheck,bun run lint,bun run fmt:check,bun run check:scaffold: pass.vitestover the speech process, the speech module, contracts, web settings/dictation and tools/notices: 1024 tests pass.apps/web/e2e/dictation.spec.ts: 13 pass, including a new Accurate consent/download/mode test.GRAM_LIVE_SPEECH=1, withGRAM_LIVE_SPEECH_ACCURATEandGRAM_LIVE_SPEECH_VAD): both live tests pass on the Nemotron export'stest_wavs/0.wavfollowed by 3 s of noise. The first final is Parakeet's punctuated "yellow lamps" sentence; the noise commits nothing.bun run check.Known limits / not verified
Vad.front(false)is used because Electron refuses external buffers; that is untested inside Electron.OfflineRecognizerandVad, CPU provider, no CoreML) and the Linux voice gate is untouched. The path is ready once a TTS-freesherpa-onnx-linux-x64build exists; the real-time factor on Linux x64 is unmeasured.use-dictation.tspassesmodethrough tostartandprewarm. After the rebase: typecheck, lint, fmt, scaffold and 1039 vitest pass;e2e/dictation.spec.ts15/15.