From 86ff0d6a9ec3eba6480e6b079a82392c0d282efa Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sat, 3 Oct 2026 11:33:48 +0200 Subject: [PATCH] Prefer the avfoundation audio output on iOS and macOS AVSampleBufferAudioRenderer is the system media path, so it gets Spatial Audio / Spatialize Stereo and head tracking, which audiounit and coreaudio output never do. iOS now uses avfoundation,audiounit like tvOS, and all macOS versions use avfoundation,coreaudio (previously only macOS 27+). --- Yattee/Services/Player/MPV/MPVClient.swift | 34 +++++++------------ .../Settings/MPVOptionsSettingsView.swift | 12 ++----- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/Yattee/Services/Player/MPV/MPVClient.swift b/Yattee/Services/Player/MPV/MPVClient.swift index 8504995c..47e1e52b 100644 --- a/Yattee/Services/Player/MPV/MPVClient.swift +++ b/Yattee/Services/Player/MPV/MPVClient.swift @@ -506,28 +506,20 @@ final class MPVClient: @unchecked Sendable { // Audio setOptionSync("audio-client-name", "Yattee") - #if os(tvOS) - // Prefer avfoundation (AVSampleBufferAudioRenderer): audiounit can't open - // 32-channel HDMI routes (Atmos "Continuous Audio Output") and stays silent. - // mpv falls back to audiounit if avfoundation fails to initialize. + // Prefer avfoundation (AVSampleBufferAudioRenderer) everywhere: it is the + // system media path, so it gets Spatial Audio / "Spatialize Stereo" and + // head tracking, which audiounit/coreaudio output never does. + // tvOS: audiounit also can't open 32-channel HDMI routes (Atmos + // "Continuous Audio Output") and stays silent. + // macOS: coreaudio fails to initialize on macOS 27 ("unable to set the + // input channel layout on the audio unit … -50"), and its failed init + // leaks a HAL hotplug listener that crashes (use-after-free) on the next + // audio device change — so coreaudio must stay second in the list. + // mpv falls back to the second AO if avfoundation fails to initialize. + #if os(macOS) + setOptionSync("ao", "avfoundation,coreaudio") + #else setOptionSync("ao", "avfoundation,audiounit") - #elseif os(iOS) - setOptionSync("ao", "audiounit") - #elseif os(macOS) - // coreaudio is the native macOS AO, but on macOS 27 beta it fails to - // initialize ("unable to set the input channel layout on the audio - // unit … -50"), leaving playback silent. Worse, mpv's coreaudio AO - // registers a HAL hotplug listener before the step that fails and its - // init-failure path never unregisters it, so every failed init leaves - // a dangling listener that crashes (use-after-free) on the next audio - // device change. On macOS 27+ put avfoundation first so the failing - // coreaudio init never runs; older macOS keeps native coreaudio with - // avfoundation as fallback. - if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 27 { - setOptionSync("ao", "avfoundation,coreaudio") - } else { - setOptionSync("ao", "coreaudio,avfoundation") - } #endif // Cache settings for network streams diff --git a/Yattee/Views/Settings/MPVOptionsSettingsView.swift b/Yattee/Views/Settings/MPVOptionsSettingsView.swift index 6e4905bf..58078675 100644 --- a/Yattee/Views/Settings/MPVOptionsSettingsView.swift +++ b/Yattee/Views/Settings/MPVOptionsSettingsView.swift @@ -120,16 +120,10 @@ private struct DefaultOptionsSection: View { options.append(("framedrop", "decoder+vo")) options.append(("audio-client-name", "Yattee")) - #if os(tvOS) - options.append(("ao", "avfoundation,audiounit")) - #elseif os(iOS) - options.append(("ao", "audiounit")) + #if os(macOS) + options.append(("ao", "avfoundation,coreaudio")) #else - if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 27 { - options.append(("ao", "avfoundation,coreaudio")) - } else { - options.append(("ao", "coreaudio,avfoundation")) - } + options.append(("ao", "avfoundation,audiounit")) #endif options.append(("cache", "yes"))