You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SayPi ships a VAD preset tuned for noisy environments (conservative) that selectVADPreset can never return, so a user in a noisy room has no way to reach it — and the one listening control they do have ("Quiet mode") moves sensitivity in the opposite direction.
Scope
Affected: src/vad/VADConfigs.ts (selectVADPreset), and the "Quiet mode" control in entrypoints/settings/tabs/general/.
Applies to both contexts the selector serves: dedicated chat hosts and generic/universal-dictation pages.
Out of scope: retuning balanced, and the exact UX of any new control (see acceptance criteria — deliberately not prescribed).
Reproduction / verification
Current selector is total and has two outcomes (src/vad/VADConfigs.ts:104):
So the reachable set is {balanced, highSensitivity}. The presets and their opening thresholds:
preset
positive
negative
redemption
reachable?
highSensitivity
0.35
0.20
12 (384ms)
yes — Quiet mode on
balanced
0.40
0.25
10 (320ms)
yes — default
conservative
0.60
0.45
8 (256ms)
no path
conservative is documented in the same file as "Noisy environments – lower sensitivity (reserved; not yet selected)", and its values are locked by test/vad/VADConfigs.spec.ts, so it is maintained but dead.
The only user-facing listening control is the "Quiet mode" checkbox (General settings), described to users as "Speak softly — picks up quieter speech…". Enabling it selects highSensitivity (positive 0.40 → 0.35), i.e. it makes the VAD more likely to open on background noise.
Expected: a user in a noisy room can bias listening toward requiring clearer speech. Actual: they can only leave it at balanced or make it more sensitive; the preset built for their case is unreachable.
Acceptance criteria
conservative is reachable in normal operation, or is deleted along with its lock test — a tuned, tested, permanently-unreachable preset is not a valid end state.
A user (or an automatic signal) in a noisy environment ends up on a preset whose thresholds are at least as strict as balanced.
The existing Quiet-mode behaviour and the balanced default are unchanged for users who don't opt in.
Whatever selects it is unit-testable at the selectVADPreset seam, without a browser.
Founder-reported symptom that prompted this (2026-07-29): STT quality noticeably worse with a washing machine running nearby. Mechanism is not established — filed as the reachability gap, not as a diagnosis of that report. Two candidate mechanisms worth measuring before choosing a fix: (a) balanced's low negativeSpeechThreshold (0.25) may not be crossed cleanly when steady broadband noise raises the probability floor, affecting where segments end; (b) noise-only segments clearing 0.40 get uploaded and transcribed. The Leverage the VAD's own confidence signal (computed, then discarded) to cut silence hallucinations — and characterize the thresholds #420 admission gate is unlikely to be involved — its floor is positiveSpeechThreshold + 0.05 on the segment's peak, which real speech clears easily.
The getUserMedia constraints are not the gap: @ricky0123/vad-web hardcodes noiseSuppression/echoCancellation/autoGainControl to true after spreading caller constraints, so browser-level noise suppression is already active and cannot be accidentally disabled by SayPi.
Problem
SayPi ships a VAD preset tuned for noisy environments (
conservative) thatselectVADPresetcan never return, so a user in a noisy room has no way to reach it — and the one listening control they do have ("Quiet mode") moves sensitivity in the opposite direction.Scope
src/vad/VADConfigs.ts(selectVADPreset), and the "Quiet mode" control inentrypoints/settings/tabs/general/.balanced, and the exact UX of any new control (see acceptance criteria — deliberately not prescribed).Reproduction / verification
Current selector is total and has two outcomes (
src/vad/VADConfigs.ts:104):So the reachable set is
{balanced, highSensitivity}. The presets and their opening thresholds:highSensitivitybalancedconservativeconservativeis documented in the same file as "Noisy environments – lower sensitivity (reserved; not yet selected)", and its values are locked bytest/vad/VADConfigs.spec.ts, so it is maintained but dead.The only user-facing listening control is the "Quiet mode" checkbox (General settings), described to users as "Speak softly — picks up quieter speech…". Enabling it selects
highSensitivity(positive 0.40 → 0.35), i.e. it makes the VAD more likely to open on background noise.Expected: a user in a noisy room can bias listening toward requiring clearer speech.
Actual: they can only leave it at
balancedor make it more sensitive; the preset built for their case is unreachable.Acceptance criteria
conservativeis reachable in normal operation, or is deleted along with its lock test — a tuned, tested, permanently-unreachable preset is not a valid end state.balanced.balanceddefault are unchanged for users who don't opt in.selectVADPresetseam, without a browser.Notes / hypotheses (non-binding)
conservativeto a noise/SNR estimate, which would make the choice automatic rather than a setting. Either direction satisfies the criteria above; the automatic one avoids adding a control users must understand.balanced's lownegativeSpeechThreshold(0.25) may not be crossed cleanly when steady broadband noise raises the probability floor, affecting where segments end; (b) noise-only segments clearing 0.40 get uploaded and transcribed. The Leverage the VAD's own confidence signal (computed, then discarded) to cut silence hallucinations — and characterize the thresholds #420 admission gate is unlikely to be involved — its floor ispositiveSpeechThreshold + 0.05on the segment's peak, which real speech clears easily.getUserMediaconstraints are not the gap:@ricky0123/vad-webhardcodesnoiseSuppression/echoCancellation/autoGainControltotrueafter spreading caller constraints, so browser-level noise suppression is already active and cannot be accidentally disabled by SayPi.