diff --git a/Yattee/Services/Player/MPV/MPVClient.swift b/Yattee/Services/Player/MPV/MPVClient.swift index e0958f87..ac8b1a15 100644 --- a/Yattee/Services/Player/MPV/MPVClient.swift +++ b/Yattee/Services/Player/MPV/MPVClient.swift @@ -463,11 +463,18 @@ final class MPVClient: @unchecked Sendable { #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. Add avfoundation - // (AVSampleBufferAudioRenderer) as a fallback so mpv self-heals: older - // macOS keeps using coreaudio, and where coreaudio can't open the - // device mpv drops to avfoundation instead of playing no sound. - setOptionSync("ao", "coreaudio,avfoundation") + // 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 3bfbd44f..ee31a357 100644 --- a/Yattee/Views/Settings/MPVOptionsSettingsView.swift +++ b/Yattee/Views/Settings/MPVOptionsSettingsView.swift @@ -123,7 +123,11 @@ private struct DefaultOptionsSection: View { #if os(iOS) || os(tvOS) options.append(("ao", "audiounit")) #else - options.append(("ao", "coreaudio,avfoundation")) + if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 27 { + options.append(("ao", "avfoundation,coreaudio")) + } else { + options.append(("ao", "coreaudio,avfoundation")) + } #endif options.append(("cache", "yes"))