我编写了访问 Apple Core Audio API 的代码,但每次运行它时,它都会返回分段错误。我确信它与我的设备上的权限有关,但我不确定需要什么权限才能让它工作。如果您知道我能做些什么来解决这个问题,我将不胜感激。
我的代码:
import ctypes
from ctypes import c_uint32, c_void_p, byref, Structure, POINTER, c_int, c_char
# Define constants
kAudioObjectSystemObject = 1
kAudioObjectPropertyScopeGlobal = 1735159650
kAudioObjectPropertyElementMaster = 0
kAudioHardwarePropertyDevices = 1684370979
kAudioDevicePropertyDeviceNameCFString = 1819173229
# Define the AudioObjectPropertyAddress structure
class AudioObjectPropertyAddress(Structure):
_fields_ = [
('mSelector', c_uint32),
('mScope', c_uint32),
('mElement', c_uint32),
]
# Load CoreAudio framework
coreaudio = ctypes.CDLL('/System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio')
# OLD PATH: '/System/Library/Frameworks/CoreAudio.framework/CoreAudio'
# Define function prototypes
coreaudio.AudioObjectGetPropertyDataSize.argtypes = [c_uint32, POINTER(AudioObjectPropertyAddress), c_uint32, c_void_p, POINTER(c_uint32)]
coreaudio.AudioObjectGetPropertyDataSize.restype = c_int
coreaudio.AudioObjectGetPropertyData.argtypes = [c_uint32, POINTER(AudioObjectPropertyAddress), c_uint32, c_void_p, c_uint32, c_void_p]
coreaudio.AudioObjectGetPropertyData.restype = c_int
def list_audio_devices():
devices = []
# Define the property address for getting the list of devices
property_address = AudioObjectPropertyAddress(
mSelector=kAudioHardwarePropertyDevices, # Removed .value
mScope=kAudioObjectPropertyScopeGlobal,
mElement=kAudioObjectPropertyElementMaster
)
# Get the size of the property data
property_data_size = c_uint32(0)
status = coreaudio.AudioObjectGetPropertyDataSize(
kAudioObjectSystemObject,
byref(property_address),
0,
None,
byref(property_data_size)
)
if status != 0:
raise RuntimeError(f"AudioObjectGetPropertyDataSize failed with status {status}")
# Determine the number of devices
device_count = property_data_size.value // ctypes.sizeof(c_uint32)
# Create an array to hold the device IDs
device_ids = (c_uint32 * device_count)()
# Get the device IDs
status = coreaudio.AudioObjectGetPropertyData(
kAudioObjectSystemObject,
byref(property_address),
0,
None,
property_data_size.value,
byref(device_ids)
)
if status != 0:
raise RuntimeError(f"AudioObjectGetPropertyData failed with status {status}")
# Get the names of the devices
for device_id in device_ids:
property_address.mSelector = kAudioDevicePropertyDeviceNameCFString # Removed .value
property_data_size = c_uint32(0)
status = coreaudio.AudioObjectGetPropertyDataSize(
device_id,
byref(property_address),
0,
None,
byref(property_data_size)
)
if status != 0:
raise RuntimeError(f"AudioObjectGetPropertyDataSize failed for device {device_id} with status {status}")
# Create a buffer for the device name
device_name = ctypes.create_string_buffer(property_data_size.value)
status = coreaudio.AudioObjectGetPropertyData(
device_id,
byref(property_address),
0,
None,
property_data_size.value,
byref(device_name)
)
if status != 0:
raise RuntimeError(f"AudioObjectGetPropertyData failed for device {device_id} with status {status}")
devices.append({
'id': device_id,
'name': device_name.value.decode('utf-8')
})
return devices
# List all devices and their IDs
devices = list_audio_devices()
for device in devices:
print(f"Device ID: {device['id']}, Device Name: {device['name']}")
错误: zsh:分段错误 /usr/local/bin/python3 /Users/MYNAME/Desktop/Core_Audio.py
我尝试以适应内存过度使用的方式重写代码。该代码的主要目标是拆分 Fromm 上层应用程序的音频通道,以便我可以自定义每个应用程序的音量,而无需更改整个计算机的音量。
您遇到的问题很可能与您设备上的权限无关。分段错误通常是由于以下原因发生的:
device_name_buffer = ctypes.create_string_buffer(property_data_size.value) 状态 = coreaudio.AudioObjectGetPropertyData( 设备 ID, byref(属性地址), 0, 没有任何, property_data_size.value, byref(设备名称缓冲区) )
if status != 0:
raise RuntimeError(f"AudioObjectGetPropertyData failed for device {device_id} with status {status}")
# Decode the device name from the buffer and free the memory
device_name = device_name_buffer.value.decode('utf-8')
del device_name_buffer # Free the allocated memory
对于 device_ids 中的 device_id: # 为每个设备创建一个新的属性地址 new_property_address = AudioObjectPropertyAddress( mSelector=kAudioHardwarePropertyDevices, # 删除 .value mScope=kAudioObjectPropertyScopeGlobal, mElement=kAudioObjectPropertyElementMaster )
property_data_size = c_uint32(0)
status = coreaudio.AudioObjectGetPropertyDataSize(
device_id,
byref(new_property_address), # Use a new property address
0,
None,
byref(property_data_size)
)
# ... rest of the code for retrieving device name ...
关于分割音频通道: 不幸的是,在 macOS 上使用 CoreAudio API 无法直接操作来自单独应用程序的音频通道。但是,您可以使用“Soundflower”(第三方应用程序)等系统实用程序或“系统偏好设置”>“声音”中的“多输出设备”等内置功能来实现类似的功能。它允许您创建虚拟输出设备,组合来自不同应用程序的音频流,然后您可以独立控制其音量。