Audio coreaudio
Manipulate macOS audio at the Core Audio HAL layer: afinfo (audio file metadata), afplay (play), afconvert (convert format/rate/bit-depth/channel layout), say (TTS), SwitchAudioSource (change default input/output/system device — brew install switchaudio-osx), audiodevice CLIs (npm/Go variants), AppleScript via osascript to drive System Preferences Sound. HAL plugins at /Library/Audio/Plug-Ins/HAL/ load virtual drivers (BlackHole 2ch/16ch/64ch, Loopback, Background Music). Aggregate Device (drift-corrected multi-in) and Multi-Output Device via Audio MIDI Setup.app or AudioHardwareCreateAggregateDevice. Use when the user asks to change default macOS audio device, route audio between apps on Mac, install BlackHole, build an Aggregate Device, convert audio files with afconvert, or script Mac audio from the terminal.From its SKILL.md
npx -y skills add damionrashford/media-os --skill audio-coreaudioAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 17 stars17 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.6 KB, as published. Nobody here has run it
Audio CoreAudio
Context: $ARGUMENTS
Quick start
- List input/output devices: → Step 1 (
macaudio.py list-devices) - Change default output: → Step 2 (
macaudio.py set-default) - Inspect an audio file: → Step 3 (
macaudio.py info) - Play a file: → Step 3 (
macaudio.py play) - Convert format/rate/bits: → Step 4 (
macaudio.py convert) - Text-to-speech: → Step 5 (
macaudio.py tts) - Build an Aggregate Device: → Step 6 (
macaudio.py aggregate-create) - List HAL virtual drivers: → Step 7 (
macaudio.py hal-plugins) - Install BlackHole virtual cable: → Step 8 (
macaudio.py blackhole-install)
When to use
- User is on macOS and needs terminal-driven audio control.
- Wants to change the default input/output/system device without clicking through System Settings → Sound.
- Wants to convert audio files with Apple's built-in
afconvert(more format coverage than SoX for Apple formats; handles CAF, M4A, ALAC natively). - Wants to build an Aggregate Device (multi-input) or Multi-Output Device (mirror output to several devices).
- Wants to install / evaluate virtual audio drivers (BlackHole, Loopback, Background Music).
Not for: Linux (use audio-pipewire), Windows (use audio-wasapi).
The script exits 2 with a helpful message if run on non-macOS.
Step 1 — List devices
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py list-devices
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py list-devices --format json
SwitchAudioSource -a underneath. Each line is <name> (<type>) where type is
input / output. If SwitchAudioSource isn't installed the script tells you
to run brew install switchaudio-osx.
Step 2 — Set default input/output/system device
macOS distinguishes three defaults: output (music/TV audio), input (mic), system (alert sounds, which can be a different device).
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py set-default "MacBook Pro Speakers"
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py set-default "Scarlett Solo" --type input
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py set-default "MacBook Pro Speakers" --type system
Device name must match exactly (spaces matter, quoting required). Use
list-devices first.
Step 3 — Inspect and play files (afinfo / afplay)
afinfo + afplay ship with macOS. No install needed.
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py info track.caf
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py play track.caf
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py play track.caf --volume 128 # 0-255
afinfo reads every Apple format (CAF, M4A/AAC/ALAC, AIFF, WAV, MP3) plus
anything the system's registered AudioToolbox components understand.
Step 4 — Convert with afconvert
afconvert is Apple's native format converter. Preferred over SoX for
Apple-specific flows (CAF, ALAC, AAC for M4A/M4R, lossless 32-bit float).
# WAV -> Apple Lossless in an M4A
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py convert \
--input in.wav --output out.m4a --format m4af
# 24-bit 96k WAV -> 16-bit 48k WAV
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py convert \
--input hi.wav --output lo.wav --format WAVE \
--rate 48000 --bit-depth 16
# Stereo -> 5.1 upmix (container must support it — CAF does)
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py convert \
--input stereo.wav --output surround.caf --format caff \
--channel-layout 5.1
FourCC codes the --format flag accepts: caff (CAF), m4af (MPEG-4 audio),
WAVE, AIFF, AIFC. Full list: afconvert -hf.
Step 5 — say + afplay TTS
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py tts "Build complete"
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py tts "hola" --voice Monica
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py tts "saved" --output voicemail.aiff
say -v '?' lists installed voices. Voices beyond the defaults (Alex, Samantha,
Daniel) require a one-time download via System Settings → Accessibility →
Spoken Content → System Voice → Customize.
Step 6 — Aggregate Device / Multi-Output Device
macOS lets you combine physical devices two ways:
- Aggregate Device — sum inputs and outputs of several devices into one logical interface. DAWs see it as a single multi-channel device. Needs drift correction when the member devices don't share a word clock.
- Multi-Output Device — mirror playback to several outputs (e.g. speakers + BlackHole + AirPods). Output-only.
This wrapper opens Audio MIDI Setup and prints the clickable steps, because
programmatic creation needs AudioHardwareCreateAggregateDevice from
CoreAudio/AudioHardware.h (Swift / Objective-C). Use when wiring for
automation:
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py aggregate-create \
--name "Studio Aggregate" \
--devices "AppleHDAEngineOutput:1B,0,0,1:0" "BlackHole2ch_UID" \
--drift-correct "BlackHole2ch_UID"
Member device UIDs come from list-devices (pass --format json for the full
UID strings).
For a truly automatable path, write the Swift snippet that calls
AudioHardwareCreateAggregateDevice — see references/virtual-drivers.md.
Step 7 — List HAL plug-ins
HAL plug-ins are .driver bundles that register virtual audio devices:
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py hal-plugins
Typical output includes BlackHole2ch.driver, BackgroundMusic.driver,
Loopback.driver, Aggregate/Multi-Output synthesizer drivers from Apple.
Global path: /Library/Audio/Plug-Ins/HAL/*.driver.
User path: ~/Library/Audio/Plug-Ins/HAL/*.driver (rare; per-user installs).
After installing or removing a HAL plug-in, coreaudiod has to rescan:
sudo pkill coreaudiod # wrapper intentionally does NOT run this
Step 8 — BlackHole (virtual cable)
BlackHole is the go-to free open-source virtual driver — works on Apple Silicon (DriverKit / AudioDriverKit) and Intel, 2ch / 16ch / 64ch variants.
The wrapper prints install instructions rather than installing automatically:
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py blackhole-install --variant 2ch
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py blackhole-install --variant 16ch
Runs the install only if the user copies the printed brew install --cask line.
See references/virtual-drivers.md for the
full BlackHole vs Loopback vs Background Music comparison.
Gotchas
- Soundflower is abandoned. It does not load on macOS 11+ / Apple Silicon. Never recommend it. Use BlackHole instead.
SwitchAudioSourcedevice names must match exactly. Trailing spaces, capitalization, and the full name (including brand prefix) all matter. Quote-wrap everything.list-devices --format jsongives you a copy-pasteable UID.- There are two "audiodevice" CLIs in the wild. An npm package
(
node-audiodevice) and a Go binary. Both predate SwitchAudioSource and have different flags. Always specify the package/binary when pointing at them; default toSwitchAudioSourcein docs. - BlackHole, Loopback, and Background Music all use DriverKit/AudioDriverKit
on Apple Silicon. Legacy kext audio drivers (Soundflower, old Loopback
versions) won't load. If a driver supposedly installs but
list-devicesdoesn't show it, SIP or kernel-extension approval is likely blocking it (System Settings → Privacy & Security → Allow). - Aggregate Device needs drift correction when members don't share a clock. Without drift correction, multi-USB-device aggregates will desync by seconds over a long session.
- Multi-Output Device cannot be a system alert device. macOS rejects it — system sounds require a real output endpoint.
afconvertfourCC codes are case-sensitive.WAVEwith-f, notwave. LikewiseAIFF/AIFC/caff/m4af.- After installing a HAL plug-in, new processes pick it up; existing ones don't.
Apps that cached
AudioDeviceIDvalues will miss it until restart. System Settings → Sound usually re-enumerates immediately. sayruns through the system output by default, not whateverset-default --type inputwas last set to. If you need say → file, pipe through--output(AIFF) orafconvertafterward for M4A/MP3.- AppleScript via osascript can hit Sound preferences via UI automation, but
it's fragile across macOS versions and requires accessibility permissions.
Prefer
SwitchAudioSourcefor scripted default changes. - CoreAudio HAL IDs are not stable across reboots. Use the device
UID (string) instead of the numeric
AudioDeviceIDwhen persisting references in scripts / plist / DAW configs. - BlackHole per-channel variants are not upgradeable in place. Uninstall
blackhole-2chbefore installingblackhole-16ch, or both drivers show up simultaneously (which is fine — they are different devices, separately named).
Examples
Example 1 — "Swap default output to my headphones"
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py list-devices # find exact name
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py set-default "Sony WH-1000XM5"
Example 2 — "Capture system audio into OBS"
-
Install BlackHole 2ch:
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py blackhole-install --variant 2ch # copy the printed brew command and run it -
In Audio MIDI Setup build a Multi-Output Device combining your speakers + BlackHole; set it as system output.
-
Point OBS's "Audio Input Capture" at BlackHole.
Example 3 — "Convert a WAV archive to Apple Lossless"
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py convert \
--input master.wav --output master.m4a --format m4af
Example 4 — "Read EXIF from an AIFF"
afinfo covers it:
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py info recording.aiff
Example 5 — "Speak build results to me"
uv run ${CLAUDE_SKILL_DIR}/scripts/macaudio.py tts "Tests passed, zero failures" --voice Samantha
Troubleshooting
SwitchAudioSource: command not found
Cause: Not installed.
Fix: brew install switchaudio-osx. The wrapper points at this in its error
output.
Default device "silently" reverts after plugging in USB interface
Cause: macOS default-reassign behavior when "When playing sound through" is
set to "whatever device is connected". Overrides your scripted default.
Fix: System Settings → Sound → Output → uncheck "Automatically switch to
newly connected devices" (macOS 14+), or persist the default in a LaunchAgent
that re-runs set-default on device change.
afconvert: Error -50 (invalid parameter)
Cause: Requested an output format/rate/bit-depth combo that the codec
rejects (e.g. ALAC in WAV container, 32-bit float into M4A).
Fix: Drop mismatched flags. ALAC belongs in m4af only; bit-depth is
AAC-ignored.
BlackHole doesn't appear after install
Cause: System Extension blocked by macOS. Fix: System Settings → Privacy & Security → scroll to the "System software was blocked" banner → Allow. Reboot. Retry.
afplay works but no sound
Cause: afplay uses the current system default output. If you set a weird
output recently (aggregate without speakers as a member), nothing audible is
reached.
Fix: Re-run set-default with a known-good physical output and retry.
Aggregate Device session drifts
Cause: No drift correction, or drift master isn't the most-stable clock. Fix: In Audio MIDI Setup, check "Drift Correction" on every non-master member. Put the interface with the best clock (Thunderbolt → PCIe card → USB 2) as master.
Reference docs
- BlackHole vs Loopback vs Background Music comparison, plus the Swift snippet
for programmatic Aggregate Device creation →
references/virtual-drivers.md.