Pin the microphone by name with a mic_device setting - #6
Open
MacphersonDesigns wants to merge 1 commit into
Open
Pin the microphone by name with a mic_device setting#6MacphersonDesigns wants to merge 1 commit into
MacphersonDesigns wants to merge 1 commit into
Conversation
Both sd.InputStream calls in ears.py opened with no device= argument, so capture always followed the OS default input. The OS re-points that the moment a headset with a mic connects, which has two consequences: the agent starts listening through the headset instead of the mic you chose, and a Bluetooth headset gets pulled out of high-quality A2DP into the narrowband HFP call profile, so playback audibly degrades mid-utterance. Adds a "mic_device" config key holding a device NAME, resolved to a sounddevice index at every stream open. Names rather than indices because indices are not stable — they shift whenever a device connects or disconnects, which is the exact event this setting exists to survive. Resolution is exact-match first, then case-insensitive substring, so "MacBook Pro" finds "MacBook Pro Microphone". Degradation follows the codebase's existing rule that the voice line degrades but never goes mute: a name matching nothing falls back to the system default and logs the available inputs once, and a device that resolves but refuses to open falls back too rather than raising. An empty value is the default and preserves current behavior exactly. Deliberately NOT named after or merged into "stt_device", which is the Whisper compute device (cpu/cuda) and is a different axis entirely. Verified on macOS with a Bluetooth headset connected and holding the system default: capture opened the pinned onboard mic (index 3) instead of the headset (index 0), and the missing-device, empty-value, partial- name and warn-once paths were each exercised without raising. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FoPSh1EzL35HJAcBj6JFjF
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.
The problem
Both
sd.InputStreamcalls inears.pyopen with nodevice=argument, so capture always follows the OS default input. The OS re-points that the moment a headset with a mic connects, which has two consequences:Measured on macOS with an ATH-M50xBT2 connected: the headset held the default input at index 0 already running at 16000 Hz (HFP), while the onboard mic sat at index 3.
The fix
A new
mic_deviceconfig key holding a device name, resolved to a sounddevice index at every stream open."MacBook Pro"resolves too.Degradation
Follows the codebase's existing rule that the voice line degrades but never goes mute:
Naming
Deliberately not merged into or named after
stt_device, which already exists and means the Whisper compute device (cpu/cuda). Different axis entirely.Verification
With the headset connected and still holding the system default, capture opened the pinned onboard mic (index 3) instead of the headset (index 0). Each degradation path was exercised without raising: missing device, empty value, partial name, and the warn-once guard across repeated lookups.
Docs added to
README.md(fine print) andTROUBLESHOOTING.md(next to the existing input-device entry).