-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
WebAudioBridge.isSupported() returns false on Safari (non-Chromium) and voice
audio is blocked entirely. The reason is that Safari silently ignores the
sampleRate option passed to new AudioContext({ sampleRate }), instead using the
hardware native rate (44.1 kHz or 48 kHz). This causes:
- Capture: mic audio arrives at the wrong sample rate → whisper STT
transcription quality is severely degraded (input is pitched/stretched). - Playback: 24 kHz kokoro TTS PCM plays at the hardware rate →
wrong speed and pitch.
The guard in WebAudioBridge.isSupported() and the validation throw in connect()
both detect this and prevent a broken mid-call experience, but the result is that
Safari users cannot use voice mode at all.
Goal
Add a software resampler AudioWorklet so the bridge operates correctly regardless
of the browser's hardware sample rate, enabling Safari support.
Proposed approach
Replace the hard UA-block with a runtime sample-rate check and inject resamplers
when needed:
-
Capture path: if
captureCtx.sampleRate !== 16_000, insert a resampling
AudioWorklet node between the mic source and theCaptureProcessor. A
polyphase or linear-interpolation resampler in pure JS (or a small WASM module)
is sufficient for 16 kHz STT input. -
Playback path: if
playbackCtx.sampleRate !== 24_000, resample the
incoming 24 kHz PCM to the hardware rate before feeding the ring buffer.
The resampler can run insidePlaybackProcessoror as a separate upstream
node. -
Remove the Safari UA guard from
isSupported()once both paths are covered.
Keep thesampleRatemismatch throw inconnect()as a last-resort fallback
until validated across device/browser combinations.
Acceptance criteria
WebAudioBridge.isSupported()returnstrueon Safari (macOS/iOS).- Voice mode (PTT + TTS playback) works correctly on Safari 17+ (macOS) and
Safari on iOS 17+. - No regression on Chrome/Firefox/Tauri.
cargo test --workspaceand TypeScript build pass.
Affected files
src/services/transport/audio/WebAudioBridge.tssrc/services/transport/audio/index.ts(isAudioSupportedcomment)