1

How can I list every actual microphones currently available in python?

Currently i am doing this:

import pyaudio p = pyaudio.PyAudio() print("Available audio input devices:") for i in range(p.get_device_count()): dev_info = p.get_device_info_by_index(i) print(f"{i}: {dev_info['name']}") device_index = int(input("Enter the index of the audio input device you want to use: ")) 

I know this also prints output devices, but the results are bloated with duplicates and things that aren't actually devices.

For reference I have 3 input devices, and 2 output devices, but the script prints 29 items.

What is the proper way of 'filtering' this to only display actual devices, aka the ones available in my Settings > System > Sound ?

2 Answers 2

1

Due to PortAudio supporting multiple APIs, you see repeated mentions of the same device but on different host APIs (for reference: https://files.portaudio.com/docs/v19-doxydocs/api_overview.html). You can simply filter it out like this:

import pyaudio pa = pyaudio.PyAudio() print("Number of devices (all APIs, input + output):"+ pa.get_device_count()) for i in range (pa.get_device_count()): device_info = pa.get_device_info_by_index(i) if device_info['maxInputChannels'] != 0 and device_info['hostApi'] == 0: print('Device ' + str(i) + ': ' + device_info['name']) 

I'm sure there's an even shorter way to do it, but essentially, it comes down to which native audio APi your application wants/needs and you count the number of input devices with the same API.

Sign up to request clarification or add additional context in comments.

Comments

0

I'm not sure if this is the most efficient solution but it works.

import pyaudio #Check language replace with microphone_check_string = "" if you don't want language functionality from sys import platform import os microphone_check_string = "" if platform == "linux" or platform == "linux2" or platform == "darwin": #get os language in linux or macos language = os.environ['LANG'] elif platform == "win32": #get os language in windows import ctypes import locale locale.getlocale() windll = ctypes.windll.kernel32 windll.GetUserDefaultUILanguage() language = locale.windows_locale[ windll.GetUserDefaultUILanguage() ] #remove character encoding for linux or macos if("UTF-8" in language): language = language.replace(".UTF-8", "") #Translate the "Microphone" text to desired language match language: case "en_US" : microphone_check_string = "Microphone" #End check language p = pyaudio.PyAudio() devices = p.get_device_count() #list of device objects(dicts) device_list = [] #list of device names. Used for detecting duplicates temp_name_list = [] for i in range(devices): # Get the device info device_info = p.get_device_info_by_index(i) # Check if this device is a microphone (an input device) if device_info.get('maxInputChannels') > 0: #get device name device_name = device_info.get("name") #check if device is duplicate if(device_name not in temp_name_list and microphone_check_string in device_name): #add device to device list device_list.append(device_info) #add device to name list temp_name_list.append(device_name) #print device names for pos, device in enumerate(device_list): print(f"{pos}: {device["name"]}") list_len = len(device_list) #handle user input while True: device_user_selected = int(input("Enter the number of the audio input device you want to use: ")) if(device_user_selected < 0 or device_user_selected >= list_len): print("Please select a device that is in the list.") else: break #do device select logic #retrieve device info by doing device_list[device_user_selected] print(device_list[device_user_selected]) 

I used code from this tutorial and added my own logic to remove duplicates and make the user input more robust.

This is the output that I get:

0: Microsoft Sound Mapper - Input 1: Microphone (Razer Seiren X) 2: Microphone (High Definition Aud 3: Primary Sound Capture Driver 4: Microphone (High Definition Audio Device) 5: Microphone (HD Audio Microphone) Enter the number of the audio input device you want to use: 1 {'index': 1, 'structVersion': 2, 'name': 'Microphone (Razer Seiren X)', 'hostApi': 0, 'maxInputChannels': 2, 'maxOutputChannels': 0, 'defaultLowInputLatency': 0.09, 'defaultLowOutputLatency': 0.09, 'defaultHighInputLatency': 0.18, 'defaultHighOutputLatency': 0.18, 'defaultSampleRate': 44100.0} 

To get even better results add the following condition "Microphone" in device_name to the condition that checks if the device is a duplicate.

Edit: Added language functionality so that the string that is checked for can be changed depending on os language. If you want to disable this set microphone_check_string = "" before pyaudio is initialized and it won't string check the name of the device.

Please reference this stack overflow answer for info about checking OS language in python: https://stackoverflow.com/a/25691701/19097807

And this answer for determining the host OS in python: https://stackoverflow.com/a/8220141/19097807

Let me know if this doesn't solve your issue or if you need help with anything else.

2 Comments

Not convinced that you should check for "Microphone" if this app needs to run on client devices, on which the language might not be English
You do have a good point. I added functionality to check the OS language. I tested across Windows, MacOS, and Linux.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.