Skip to content

Add wired input lookup for Bluetooth default mics - #7284

Merged
ComputelessComputer merged 6 commits into
mainfrom
fix/prefer-wired-mic-over-bluetooth
Sep 3, 2026
Merged

Add wired input lookup for Bluetooth default mics#7284
ComputelessComputer merged 6 commits into
mainfrom
fix/prefer-wired-mic-over-bluetooth

Conversation

@ComputelessComputer

@ComputelessComputer ComputelessComputer commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Opening a Bluetooth headset mic forces HFP: the headset gates the mic to silence between words (26-52% zeros measured on Shokz and Jabra) and drops the wearer to 16 kHz. Expose a helper that picks a wired input (built-in, then USB) when the default input is Bluetooth so the capture path can avoid the headset mic.


Note

Medium Risk
Changes default capture device selection and Windows device typing, which can alter which mic opens and AEC/isolation behavior; dropout detection is additive but affects live session UX.

Overview
When the system default input is a Bluetooth headset and the user did not pick a mic, capture on macOS/Windows now opens a wired input instead (built-in/PCI, then USB), skipping loopback/line-in endpoints, so opening the headset mic does not force HFP gating and narrowband audio. The source tracks active_mic_device separately from the user choice; progress/errors and GetMicDevice report what is actually open.

Windows transport classification now uses the adapter device path (e.g. bthhfenum) so in-box “Hands-Free” endpoints count as Bluetooth, not only names containing “bluetooth”.

After a swap, mic_isolated is no longer asserted even with headphone-only output (replacement is treated as a room mic). A DropoutMonitor watches raw mic for high exact-zero ratios and emits mic_dropouts once per stream (surfaced through listener and transcription events) when gating still happens.

Reviewed by Cursor Bugbot for commit fa366e8. Bugbot is set up for automated code reviews on this repo. Configure here.

@netlify

netlify Bot commented Sep 3, 2026

Copy link
Copy Markdown

Deploy Preview for anarlog canceled.

Name Link
🔨 Latest commit fa366e8
🔍 Latest deploy log https://app.netlify.com/projects/anarlog/deploys/6a998712d3fe890008cd5077

Comment thread crates/audio-device/src/lib.rs
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from fe13c90 to 9def30c Compare September 3, 2026 08:07
@ComputelessComputer
ComputelessComputer force-pushed the fix/system-audio-follows-meeting-app branch from f6a0796 to ed60341 Compare September 3, 2026 08:13
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 9def30c to d356f37 Compare September 3, 2026 08:13
@ComputelessComputer
ComputelessComputer force-pushed the fix/system-audio-follows-meeting-app branch from ed60341 to 68c187a Compare September 3, 2026 08:25
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from d356f37 to 8624979 Compare September 3, 2026 08:25
@ComputelessComputer
ComputelessComputer force-pushed the fix/system-audio-follows-meeting-app branch from 68c187a to f0c92c1 Compare September 3, 2026 09:28
@ComputelessComputer
ComputelessComputer changed the base branch from fix/system-audio-follows-meeting-app to fix/live-speaker-assignments-in-engine September 3, 2026 09:29
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 8624979 to 2309198 Compare September 3, 2026 09:29
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from cad6b3b to 8c0f273 Compare September 3, 2026 09:39
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 2309198 to dfa188c Compare September 3, 2026 09:39
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from 8c0f273 to c67c3c8 Compare September 3, 2026 10:00
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from dfa188c to 2d1f2c7 Compare September 3, 2026 10:00
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from c67c3c8 to a9f1afd Compare September 3, 2026 10:06
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 2d1f2c7 to 8dbca1c Compare September 3, 2026 10:06
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from a9f1afd to f3a2de5 Compare September 3, 2026 10:18
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 8dbca1c to c48d822 Compare September 3, 2026 10:18
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from f3a2de5 to 333c46e Compare September 3, 2026 10:28
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from c48d822 to 83374cb Compare September 3, 2026 10:28
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from 333c46e to ba0ee06 Compare September 3, 2026 10:30
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 83374cb to f9d101f Compare September 3, 2026 10:30
Comment thread crates/listener-core/src/actors/source/pipeline.rs
Comment thread crates/listener-core/src/actors/source/stream.rs
Comment thread crates/listener-core/src/actors/source/mod.rs
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from ba0ee06 to 3dca13c Compare September 3, 2026 10:52
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 22b6b52 to 5833941 Compare September 3, 2026 10:52
Comment thread crates/audio-device/src/lib.rs
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from 3dca13c to 980c2cc Compare September 3, 2026 11:13
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 194dfb0 to cf5d338 Compare September 3, 2026 11:13
Comment thread crates/audio-device/src/lib.rs
Comment thread crates/listener-core/src/actors/source/stream.rs
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from 980c2cc to f73bcd3 Compare September 3, 2026 11:24
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from cf5d338 to 531311d Compare September 3, 2026 11:24

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1a969af. Configure here.

Comment thread crates/audio-device/src/device.rs Outdated
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 1a969af to 35538e9 Compare September 3, 2026 11:41
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from 87f5307 to fa8adfe Compare September 3, 2026 11:41
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 35538e9 to ada42ae Compare September 3, 2026 11:41
@ComputelessComputer
ComputelessComputer force-pushed the fix/live-speaker-assignments-in-engine branch from fa8adfe to 75df9ba Compare September 3, 2026 11:41
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch 3 times, most recently from 8c0e6c7 to cbe5112 Compare September 3, 2026 11:57
Base automatically changed from fix/live-speaker-assignments-in-engine to main September 3, 2026 14:41
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from cbe5112 to 2d858bc Compare September 3, 2026 14:41
Opening a Bluetooth headset mic forces HFP: the headset gates the mic to silence between words (26-52% zeros measured on Shokz and Jabra) and drops the wearer to 16 kHz. Expose a helper that picks a wired input (built-in, then USB) when the default input is Bluetooth so the capture path can avoid the headset mic.
The lookup alone did not change capture: when the user has not picked a mic, open a wired replacement instead of a Bluetooth default, and remember the device that actually opened. Bluetooth headsets still in call mode gate the mic between words; if 15%+ of samples over 5s are exact zeros, emit mic_dropouts once per stream so the UI can warn.
The dropout monitor waits for the mic's first non-zero sample, so the zero padding dual capture inserts while the speaker stream leads a slow-starting mic is not reported as gating. The Bluetooth default swap is gated to macOS/Windows: Linux opens the mic through cpal/ALSA, whose names never match PulseAudio sources, so the lookup could not open a replacement there. StreamFailed and recorder failures report active_mic_device, the input that was actually opened.
Windows' in-box Bluetooth driver names HFP endpoints "Headset (X Hands-Free AG Audio)" without ever saying "Bluetooth", so the name heuristic left them Unknown: the wired-mic swap never triggered on a Bluetooth default and could pick a second headset as the replacement. Read the adapter device path through IDeviceTopology and classify by its bus enumerator (BTH*, USB, HDAUDIO, INTELAUDIO, SWD/ROOT), falling back to the name, which now also treats "hands-free" as Bluetooth.
Stereo Mix, Line In, and similar capture endpoints share the built-in transport with the real microphone and could win on list order, so the swap would record the output mix or an empty jack. Filter them out by name and, within a transport rank, prefer a device that calls itself a microphone.
The headphone verdict vouched for the user's own setup, where the headset mic sat on their head. Once the input is swapped to a wired room mic, nothing says it hears only them, so mic_isolated is false and voiceprint persistence stops confirming whatever that mic picks up as the local user. CaptureSettings carries headphone_output separately so the routing watcher keeps the real headphone baseline and AEC stays off.
@ComputelessComputer
ComputelessComputer force-pushed the fix/prefer-wired-mic-over-bluetooth branch from 2d858bc to fa366e8 Compare September 3, 2026 14:41
@ComputelessComputer
ComputelessComputer merged commit 969ad4b into main Sep 3, 2026
21 of 22 checks passed
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