You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Audio dropouts on macOS: the 1 s output-device check creates AudioUnits via cpal description() #928
On macOS, every decoded source (Local Files, Subsonic, YouTube) plays with short, random audio dropouts on a USB output device (USB headphones through a dock, 48 kHz, 512-frame buffer). Spotify through native streaming (librespot) plays clean, and the same file plays clean in mpv.
The CoreAudio log shows why. While a file plays, spotatui keeps creating and connecting AUHAL units on the output device: in a 50 s --play-file run I counted 137 AudioConverter ... Created a new in process converter lines and 275 AUHAL ... SelectDevice lines from the spotatui process, a steady ~3 per second. mpv playing the same file logs none.
Cause
LocalPlayer's device-moved check (src/infra/audio/player.rs, DEVICE_CHECK_INTERVAL = 1 s) calls default_output_name() → device_name() → cpal's Device::description(). In cpal 0.17.1 the CoreAudio description() (src/host/coreaudio/macos/device.rs) calls supported_input_configs() and supported_output_configs(), and each of those instantiates an AudioUnit through audio_unit_from_device() just to read the I/O buffer-size range. So once a second, two or more AudioUnits are created and connected to the device that is playing, and that churn makes the USB output glitch.
Fix that works for me
Compare the device id instead of the description. id() only reads kAudioDevicePropertyDeviceUID, and device_name is only used to tell whether the default output changed:
With v0.46.0 plus this change, built with the release features for macOS, the same 50 s run logs 2 converters, both at startup when the sink opens, and none during playback. I will confirm here once I have listened to it for a while.
Steps to reproduce
macOS on Apple Silicon with a USB audio output as the default device.
spotatui --play-file some.mp3 (or play any Local Files, Subsonic or YouTube track).
In another terminal: log stream --style compact --predicate 'process == "spotatui"' | grep "Created a new in process converter". About 3 lines per second appear while the file plays. Audible dropouts follow on USB devices.
Frontend
TUI
Source
Local Files, Subsonic (Navidrome 0.64.2), YouTube
spotatui version
0.46.0
OS
macOS 27.0.1 (Apple Silicon)
How you installed spotatui
Homebrew tap LargeModGames/spotatui (the patched build: cargo build --release from the v0.46.0 tag)
On macOS, decoded sources (Local Files, Subsonic, YouTube) have short random audio dropouts on a USB output device. Spotify through native streaming plays clean. The reporter traced this to the once-a-second output-device check in LocalPlayer. That check calls cpal's Device::description(), and on CoreAudio this creates and connects AudioUnits on the playing device about 3 times a second. They propose comparing the device id instead of the description, which in their test removed the extra AudioUnit creation during playback. The changelog does not show a fix yet.
Key points
macOS 27.0.1 on Apple Silicon with USB headphones through a dock (48 kHz, 512-frame buffer), spotatui 0.46.0, TUI.
Local Files, Subsonic (Navidrome 0.64.2) and YouTube drop out. Spotify through librespot and mpv play the same audio clean.
In a 50 s --play-file run, CoreAudio logged 137 'Created a new in process converter' lines and 275 'AUHAL SelectDevice' lines, about 3 per second. mpv logged none.
Their stated cause: device_name() calls cpal 0.17.1 description(), which on CoreAudio runs supported_input_configs() and supported_output_configs(). Each of those creates an AudioUnit.
Proposed fix: use device.id() in device_name(). With it, only 2 converters appear, both at startup. The reporter has not yet confirmed by ear over a long listen.
Where to look
src/infra/audio/player.rs: device_lost() runs the default-output check under DEVICE_CHECK_INTERVAL (1 s). device_name() and default_output_name() call description(). The sink also stores device_name when it opens. Existing test
src/core/driver/mod.rs: The driver tick calls player.device_lost() for decoded sources and the queue, so the check runs about once a second during playback.
src/infra/audio/AGENTS.md: Gives the design rules for the default-output check: one device read a second, and an unreadable name counts as 'cannot tell'.
What would help
Whether the dropouts go away after a longer listen with the id-based patch (the reporter said they will confirm).
Whether the dropouts also happen on the built-in output or on non-USB devices, or only on USB.
Possible duplicates: none found
Compared against 45 open and 100 recently closed issues.
Update: I have been listening with the patched build on the same USB setup (Local Files, Subsonic and YouTube), and the dropouts are gone so far. The brew 0.46.0 binary on the same file still drops out.
I can take this one - the diagnosis matches what cpal 0.17.1 does (description() builds AudioUnits through the config queries, id() only reads the device UID), and the fix is small
Activity
spotatui commentedon Oct 23, 2026
🎧 spotatui triage
Auto-triaged with
claude-opus-5-5.Label:
bugLikely area: infra/audio (decoded-source LocalPlayer device-moved check)
Summary
On macOS, decoded sources (Local Files, Subsonic, YouTube) have short random audio dropouts on a USB output device. Spotify through native streaming plays clean. The reporter traced this to the once-a-second output-device check in LocalPlayer. That check calls cpal's Device::description(), and on CoreAudio this creates and connects AudioUnits on the playing device about 3 times a second. They propose comparing the device id instead of the description, which in their test removed the extra AudioUnit creation during playback. The changelog does not show a fix yet.
Key points
Where to look
src/infra/audio/player.rs: device_lost() runs the default-output check under DEVICE_CHECK_INTERVAL (1 s). device_name() and default_output_name() call description(). The sink also stores device_name when it opens. Existing testsrc/core/driver/mod.rs: The driver tick calls player.device_lost() for decoded sources and the queue, so the check runs about once a second during playback.src/infra/audio/AGENTS.md: Gives the design rules for the default-output check: one device read a second, and an unreadable name counts as 'cannot tell'.What would help
Possible duplicates: none found
Compared against 45 open and 100 recently closed issues.
leonardoprimero commentedon Oct 23, 2026
Update: I have been listening with the patched build on the same USB setup (Local Files, Subsonic and YouTube), and the dropouts are gone so far. The brew 0.46.0 binary on the same file still drops out.
niukanen1 commentedon Oct 24, 2026
I can take this one - the diagnosis matches what cpal 0.17.1 does (description() builds AudioUnits through the config queries, id() only reads the device UID), and the fix is small
fix(audio): read the device id instead of its description on macOS