diff --git a/Model/Player/Backends/AVPlayerBackend.swift b/Model/Player/Backends/AVPlayerBackend.swift index 2548ad1c..02199afd 100644 --- a/Model/Player/Backends/AVPlayerBackend.swift +++ b/Model/Player/Backends/AVPlayerBackend.swift @@ -178,6 +178,12 @@ final class AVPlayerBackend: PlayerBackend { return stream.kind == .hls || stream.kind == .stream } + func isFastLoadingFormat(_ stream: Stream) -> Bool { + // HLS and stream formats load quickly + // Non-streamable MP4/AVC1 formats may take a long time + return stream.kind == .hls || stream.kind == .stream + } + func playStream( _ stream: Stream, of video: Video, diff --git a/Model/Player/PlayerQueue.swift b/Model/Player/PlayerQueue.swift index b24dec4f..ef06b4b3 100644 --- a/Model/Player/PlayerQueue.swift +++ b/Model/Player/PlayerQueue.swift @@ -133,6 +133,26 @@ extension PlayerModel { let profile = qualityProfile ?? .defaultProfile + // For AVPlayer, prefer fast-loading formats (HLS/stream) over non-streamable formats + // to avoid long loading times when switching backends + if activeBackend == .appleAVPlayer, let avBackend = backend as? AVPlayerBackend { + // Try to find a fast-loading stream first + let fastLoadingStreams = availableStreams.filter { backend.canPlay($0) && avBackend.isFastLoadingFormat($0) } + if let fastStream = backend.bestPlayable( + fastLoadingStreams.filter { profile.isPreferred($0) }, + maxResolution: profile.resolution, formatOrder: profile.formats + ) { + return fastStream + } + // Fallback to any fast-loading stream + if let fastStream = backend.bestPlayable( + fastLoadingStreams, + maxResolution: profile.resolution, formatOrder: profile.formats + ) { + return fastStream + } + } + // First attempt: Filter by both `canPlay` and `isPreferred` if let streamPreferredForProfile = backend.bestPlayable( availableStreams.filter { backend.canPlay($0) && profile.isPreferred($0) },