Skip to content

fix(transcription): resample from the real capture sample rate#6

Open
farce1 wants to merge 1 commit into
mainfrom
fix/transcription-sample-rate
Open

fix(transcription): resample from the real capture sample rate#6
farce1 wants to merge 1 commit into
mainfrom
fix/transcription-sample-rate

Conversation

@farce1

@farce1 farce1 commented Jun 14, 2026

Copy link
Copy Markdown
Owner

What

The transcription worker hard-coded a 48 kHz → 16 kHz resampler (worker.rs), but capture falls back to the device's native rate when it can't force 48 kHz F32 (capture.rs select_mic_config). The most common real case: Bluetooth headset mics in HFP mode deliver 16 kHz (AirPods etc.). Those 16 kHz samples were resampled as if 48 kHz → ~3× speed/pitch distortion → effectively garbage transcripts for a large slice of meeting users. The Opus-encoded OGG already used the real rate, so only the transcription path was wrong.

Fix

  • RecordingState now carries transcription_sample_rate, set from the stream that actually feeds ASR: mic rate in Mic/Both modes, loopback rate in System mode (transcription_source_rate helper).
  • Plumbed through StartWorkerArgsWorkerConfig → the worker's AudioResampler::new(real_rate, 16k, …) (with a zero-guard fallback to 48 kHz).
  • The 48 kHz path is byte-identical; only non-48k devices change (now correct).

Verification (TDD)

  • RED→GREEN: transcription_source_rate tests — demonstrated RED by mimicking the old hard-coded 48k (tests failed left: 48000, right: 44100), then GREEN with the real selection.
  • Added resampler tests proving correct handling of 16 kHz and 44.1 kHz inputs.
  • Rust gate locally: clippy --all-targets --all-features -- -D warnings ✅; full cargo test → 5 new tests pass, only the pre-existing model_archive_consts_tests (REPLACE_WITH_ placeholders) fail, unrelated.

Note on interaction with #5

With #5 (Both-mode mic+system downmix) also merged, Both mode resamples at the mic rate; if mic and system rates differ, the system half is mis-resampled — the same pre-existing mixed-rate limitation flagged in #5. The common case (both 48 kHz) is correct. A fuller fix is canonical-rate normalization at capture (a larger, riskier change worth a dedicated decision).

⚠️ CI will be red — not because of this PR

main is red on three maintainer-only release blockers (SHA256/pubkey REPLACE_WITH_ placeholders, uncommitted vendor/vc_redist.x64.exe, separate frontend failure). Verified locally with a temporary untracked vendor placeholder. Do not merge until release prep is complete. Staged Track-A fix from the Handy vs openNotes transcription review; code-only, no new deps.

The transcription worker hard-coded a 48kHz->16kHz resampler, but capture
falls back to the device's native rate when it can't force 48kHz F32 —
notably Bluetooth headset mics (HFP) deliver 16kHz. Those samples were then
resampled as if 48kHz, ~3x speed-distorting the audio into garbage ASR.

Plumb the actual capture rate (mic in Mic/Both modes, loopback in System)
from RecordingState through StartWorkerArgs/WorkerConfig into the resampler.
The 48kHz path stays byte-identical; non-48k devices are now correct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant