Skip to content

Conversation

@show0000
Copy link

Summary

This PR improves audio device selection logic and refactors duplicated code in the sounddevice backend.

Background

The original get_input_device_id() and get_output_device_id() methods had some areas for improvement:

  1. Device fallback behavior: When the named device wasn’t found, both methods returned sd.default.device[1], which represents the default output device. This could cause issues for get_input_device_id() when trying to use an output device for recording.
  2. Code organization: The two methods contained nearly identical logic that could be extracted into a shared helper.

Changes

This PR introduces the following improvements:

  • Extracts shared device-finding logic into a _find_device_id(name_contains, device_type) helper method
  • Uses dynamic channel_key based on device type: "max_input_channels" or "max_output_channels"
  • Implements proper fallback: searches for the first available device with the appropriate channel type
  • Provides clearer error messages via RuntimeError when no suitable device is available
  • Fixes a small typo: logger.warningt → logger.warning

Testing

  • Tested on macOS without ReSpeaker device
  • Verified proper fallback to system default audio devices
  • Confirmed input/output device types are correctly distinguished
  • No crashes when the named device (“respeaker”) is not found

Result

Both methods now consistently return valid devices of the correct type (input or output), which should help prevent issues when audio hardware configurations vary across different systems.

@FabienDanieau
Copy link
Contributor

Thanks for the PR! I’ve reverted to the default setting, which uses the speaker or microphone selected at the system level.
What do you think about trying to first fallback to the default device, and if that fails, switch to another appropriate sound card?

@show0000
Copy link
Author

Hi, that sounds good! Finding the default device first is the natural approach.
Thanks for the comments!

@FabienDanieau
Copy link
Contributor

Hi, that sounds good! Finding the default device first is the natural approach.

Do you want to do it?
Also we changed the _init_respeaker_usb to better handle the usb error. Let us know if it's ok for you

@show0000 show0000 force-pushed the feature/fix-sounddevice-getinputdeviceid-issue branch from abd9460 to 391262e Compare October 21, 2025 23:06
@show0000
Copy link
Author

Yes, I updated the sound device detection to fall back to the default device first, as you suggested.

Comment on lines 200 to 209
channel_key = f"max_{device_type}_channels"

# return default device with appropriate channels
for idx, dev in enumerate(devices):
if (
name_contains.lower() in dev["name"].lower()
and dev["max_output_channels"] > 0
):
if dev.get(channel_key, 0) > 0:
return idx
# Return default output device if not found

Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't consider the name_contains at all :/

Copy link
Contributor

@andimarafioti andimarafioti left a comment

Choose a reason for hiding this comment

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

This won't work in the advertised way. Ie, if you query with a given name, it will still return first the default device if it has an input/output channel.

…unddevice backend

The original get_input_device_id() and get_output_device_id() had two issues:
1. Both incorrectly returned sd.default.device[1] (default OUTPUT device) as fallback
2. Nearly identical code duplicated between the two methods

This caused failures when:
- get_input_device_id() returned an output-only device for recording
- get_output_device_id() always returned the same device regardless of type

Changes:
- Extract shared logic into _find_device_id(name_contains, device_type) helper
- Use dynamic channel_key: "max_input_channels" or "max_output_channels"
- Proper fallback: search for first device with appropriate channel type
- Raise clear RuntimeError if no suitable device exists
- Fix typo: logger.warningt → logger.warning

This ensures both methods always return valid devices of the correct type.
…rch in sounddevice backend

Updated device selection logic to return the first available device with appropriate
channels before searching by device name. This provides better compatibility across
different audio hardware configurations while maintaining ReSpeaker support as fallback.
…ackend

Reorder _find_device_id logic to search by device name first before
falling back to the first available device with appropriate channels.
@show0000 show0000 force-pushed the feature/fix-sounddevice-getinputdeviceid-issue branch from 391262e to ce55b29 Compare October 23, 2025 14:40
@show0000
Copy link
Author

You’re right, @andimarafioti. I missed that. I’ve reprioritized _find_device_id() now. Thanks

@FabienDanieau
Copy link
Contributor

Hi, could integrate the new changes made by @andimarafioti ?
What does sounddevice.query_devices(None, kind="input") return for you?

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.

3 participants