Skip to content

add support for loopback recording on macOS 14.2+#196

Open
TnTora wants to merge 1 commit intobastibe:masterfrom
TnTora:master
Open

add support for loopback recording on macOS 14.2+#196
TnTora wants to merge 1 commit intobastibe:masterfrom
TnTora:master

Conversation

@TnTora
Copy link
Copy Markdown
Contributor

@TnTora TnTora commented Jan 14, 2026

This is my first attempt at integrating loopback recording on Mac as mentioned in #194.

For now, I placed the code necessary to generate the loopback device under the helper class _CoreAudio. Let me know if you would prefer it having its own helper class.

Based on the requirements for this sample project from Apple, I decided to check for loopback support using platform.mac_ver and setting 14.2 as a minimum requirement.

With the current implementation, once the user calls all_microphones(include_loopback=True) for the first time, a loopback device is created. Its id is used as a key in the dictionary _CoreAudio.loopback_devices while the id of the tap object is stored as its value. Whether or not a device is loopback is determined by its id being present in the dictionary.

This id values can be used to destroy the device. I am uncertain whether or not there is a need to actively destroy every device. I set them up to be private which means they are linked to, and only accessible from, the process which created them and from my observations they seem to disappear once the process is stopped.

If I can manage to make process inclusion and exclusion work under cffi, I was thinking the create_loopback_device function could be exposed to the user to give better control over the tap options. If you think it would be outside the scope of this library let me know.

@bastibe
Copy link
Copy Markdown
Owner

bastibe commented Apr 12, 2026

Sorry for sleeping on this for several months.

This looks very promising. However, it only adds a global loopback, and the loopback device does not appear to be destroyed properly. At least, on my machine, it only works the first time. If I run python again, it fails with

>>> import soundcard
>>> mics = soundcard.all_microphones(include_loopback=True)
'AudioHardwareCreateAggregateDevice' Error Status: 1852797029

Comment thread soundcard/coreaudio.py
_objc.objc_msgSend(NSAutoreleasePool, _objc.sel_registerName(b"release"))

if status == 0:
cls.loopback_devices[aggr_id[0]] = tap_id[0]
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

this only ever assigns one device

Comment thread soundcard/coreaudio.py
_ca.AudioHardwareDestroyProcessTap(tap_id[0])

@classmethod
def destroy_loopback_device(cls, aggr_id):
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

this is never called, right?

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.

2 participants