{"id":19690985,"url":"https://github.com/insidegui/audiocap","last_synced_at":"2025-05-16T19:07:29.109Z","repository":{"id":240285369,"uuid":"802202935","full_name":"insidegui/AudioCap","owner":"insidegui","description":"Sample code for recording system audio on macOS 14.4+","archived":false,"fork":false,"pushed_at":"2025-02-05T18:59:07.000Z","size":3907,"stargazers_count":335,"open_issues_count":0,"forks_count":33,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-05-16T18:19:08.678Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/insidegui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-17T18:10:43.000Z","updated_at":"2025-05-16T12:59:32.000Z","dependencies_parsed_at":"2025-02-24T02:00:20.140Z","dependency_job_id":"22aab143-d254-4420-b0ac-34de0d689b7d","html_url":"https://github.com/insidegui/AudioCap","commit_stats":null,"previous_names":["insidegui/audiocap"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insidegui%2FAudioCap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insidegui%2FAudioCap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insidegui%2FAudioCap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insidegui%2FAudioCap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/insidegui","download_url":"https://codeload.github.com/insidegui/AudioCap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254592395,"owners_count":22097013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T19:07:35.283Z","updated_at":"2025-05-16T19:07:29.089Z","avatar_url":"https://github.com/insidegui.png","language":"Swift","readme":"# AudioCap\n\nWith macOS 14.4, Apple introduced new API in CoreAudio that allows any app to capture audio from other apps or the entire system, as long as the user has given the app permission to do so.\n\nUnfortunately this new API is poorly documented and the nature of CoreAudio makes it really hard to figure out exactly how to set things up so that your app can use this new functionality.\n\nThis project is provided as documentation for this new API to help developers of audio apps.\n\nhttps://github.com/insidegui/AudioCap/assets/67184/95d72d1f-a4d6-4544-9d2f-a2ab99507cfc\n\n## API Description\n\nHere’s a brief summary of the new API added in macOS 14.4 and how to put everything together.\n\n### Permission\n\nAs you’d expect, recording audio from other apps or the entire system requires a permission prompt.\n\nThe message for this prompt is defined by adding the `NSAudioCaptureUsageDescription` key to the app’s Info.plist. This key is not listed in the Xcode dropdown, you have to enter it manually. \n\nThere’s no public API to request audio recording permission or to check if the app has that permission. This project implements permission check/request using private API from the TCC framework, but there is a build-time flag to disable private API usage, in which case the permission will be requested the first time audio recording is started in the app.\n\n### Process Tap Setup\n\nAssuming the app has audio recording permission, setting up and recording audio from other apps can be done by performing the following steps:\n\n- Get the PID of the process you wish to capture\n- Use [kAudioHardwarePropertyTranslatePIDToProcessObject](https://developer.apple.com/documentation/coreaudio/kaudiohardwarepropertytranslatepidtoprocessobject) to translate the PID into an `AudioObjectID`\n- Create a [CATapDescription](https://developer.apple.com/documentation/coreaudio/catapdescription) for the object ID above, and set (or just get) its `uuid` property, which will be needed later\n- Call [AudioHardwareCreateProcessTap](https://developer.apple.com/documentation/coreaudio/4160724-audiohardwarecreateprocesstap) with the tap description to create the tap, which gets its own `AudioObjectID`\n- Create a dictionary for your aggregate device that includes `[kAudioSubTapUIDKey: \u003cyour tap description uuid string\u003e]` in its `kAudioAggregateDeviceTapListKey` (you probably want to configure other things, such as setting `kAudioAggregateDeviceIsPrivateKey` to true so that it doesn’t show up globally)\n- Call [AudioHardwareCreateAggregateDevice](https://developer.apple.com/documentation/coreaudio/1422096-audiohardwarecreateaggregatedevi) with the dictionary above\n- Read `kAudioTapPropertyFormat` from the process tap to get its `AudioStreamBasicDescription`, then create an `AVAudioFormat` matching the description, this will be needed later\n- Create an `AVAudioFile` for writing with your desired settings\n- Call `AudioDeviceCreateIOProcIDWithBlock` to set up a callback for your aggregate device\n- Inside the callback, create an `AVAudioPCMBuffer` passing in your format; you can use `bufferListNoCopy` with `nil` deallocator then just call `write(from:)` on your audio file, passing in the buffer\n- Call `AudioDeviceStart` with the aggregate device and IO proc ID\n- Remember to call all your `Audio...Stop` and `Audio...Destroy` cleanup functions\n- Let the `AVAudioFile` deinit to close it\n- Now you have an audio file with a recording from the system or app\n\nThanks to [@WFT](https://github.com/WFT) for helping me with this project.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsidegui%2Faudiocap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finsidegui%2Faudiocap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsidegui%2Faudiocap/lists"}