mirror of
https://github.com/yattee/yattee.git
synced 2026-07-20 14:22:02 +00:00
Remove Enable DASH setting; make DASH a last-resort format
Drop the dashEnabled toggle and its plumbing. Stream auto-selection now keeps DASH as a candidate but ranks it strictly below progressive and HLS formats, so DASH is only chosen when it is the only format available (including live-stream fallback after HLS). The manual quality selector hides DASH entirely on iOS/tvOS/macOS. Reconciles BackendSwitcher, which previously treated HLS/DASH equally, to use the same DASH-last ranking.
This commit is contained in:
@@ -20,7 +20,6 @@ enum SettingsKey: String, CaseIterable {
|
||||
case cellularQuality
|
||||
case autoplay
|
||||
case backgroundPlayback
|
||||
case dashEnabled
|
||||
case preferredAudioLanguage
|
||||
case preferredSubtitlesLanguage
|
||||
case resumeAction
|
||||
|
||||
@@ -70,19 +70,6 @@ extension SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether DASH streams are enabled (MPV only).
|
||||
/// Disabled by default as DASH can be unreliable with some Invidious instances.
|
||||
var dashEnabled: Bool {
|
||||
get {
|
||||
if let cached = _dashEnabled { return cached }
|
||||
return bool(for: .dashEnabled, default: false)
|
||||
}
|
||||
set {
|
||||
_dashEnabled = newValue
|
||||
set(newValue, for: .dashEnabled)
|
||||
}
|
||||
}
|
||||
|
||||
var allowSoftwareDecodedFormats: Bool {
|
||||
get {
|
||||
if let cached = _allowSoftwareDecodedFormats { return cached }
|
||||
|
||||
@@ -34,7 +34,6 @@ final class SettingsManager {
|
||||
var _preferredQuality: VideoQuality?
|
||||
var _cellularQuality: VideoQuality?
|
||||
var _backgroundPlaybackEnabled: Bool?
|
||||
var _dashEnabled: Bool?
|
||||
var _preferredAudioLanguage: String?
|
||||
var _preferredSubtitlesLanguage: String?
|
||||
var _playerVolume: Float?
|
||||
@@ -415,7 +414,6 @@ final class SettingsManager {
|
||||
_preferredQuality = nil
|
||||
_cellularQuality = nil
|
||||
_backgroundPlaybackEnabled = nil
|
||||
_dashEnabled = nil
|
||||
_preferredAudioLanguage = nil
|
||||
_preferredSubtitlesLanguage = nil
|
||||
_playerVolume = nil
|
||||
|
||||
@@ -12181,16 +12181,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings.playback.dash" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Enable DASH"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings.playback.macOS.autoResizePlayer" : {
|
||||
"comment" : "Toggle for automatically resizing player window to match video aspect ratio",
|
||||
"localizations" : {
|
||||
|
||||
@@ -306,16 +306,13 @@ final class BackendSwitcher {
|
||||
filteredMuxed = muxedStreams
|
||||
}
|
||||
|
||||
// Sort: prefer non-HLS/DASH (progressive) formats, then by resolution
|
||||
// Sort: prefer progressive formats, then HLS, and only fall back to DASH as a last
|
||||
// resort (DASH should never be chosen when any other format is available).
|
||||
let sortedMuxed = filteredMuxed.sorted { s1, s2 in
|
||||
let format1 = StreamFormat.detect(from: s1)
|
||||
let format2 = StreamFormat.detect(from: s2)
|
||||
let isAdaptive1 = format1 == .hls || format1 == .dash
|
||||
let isAdaptive2 = format2 == .hls || format2 == .dash
|
||||
|
||||
// Prefer progressive formats for non-live content
|
||||
if isAdaptive1 != isAdaptive2 {
|
||||
return !isAdaptive1 // non-adaptive (false) comes first
|
||||
let rank1 = muxedFormatRank(StreamFormat.detect(from: s1))
|
||||
let rank2 = muxedFormatRank(StreamFormat.detect(from: s2))
|
||||
if rank1 != rank2 {
|
||||
return rank1 < rank2
|
||||
}
|
||||
return (s1.resolution ?? .p360) > (s2.resolution ?? .p360)
|
||||
}
|
||||
@@ -332,6 +329,17 @@ final class BackendSwitcher {
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Ranks muxed formats for fallback selection (lower = preferred).
|
||||
/// Progressive formats win, then HLS; DASH is the last resort and is only
|
||||
/// selected when it is the only format available.
|
||||
private func muxedFormatRank(_ format: StreamFormat) -> Int {
|
||||
switch format {
|
||||
case .dash: return 2
|
||||
case .hls: return 1
|
||||
default: return 0 // progressive
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns codec priority for video streams (higher = better for MPV).
|
||||
/// AV1 > VP9 > H.264/AVC
|
||||
private func videoCodecPriority(_ codec: String?) -> Int {
|
||||
|
||||
@@ -1901,7 +1901,6 @@ final class PlayerService {
|
||||
|
||||
private func selectStreams(for backendType: PlayerBackendType, from streams: [Stream]) -> (video: Stream, audio: Stream?)? {
|
||||
let supportedFormats = backendType.supportedFormats
|
||||
let dashEnabled = settingsManager?.dashEnabled ?? false
|
||||
|
||||
// Get user's original quality preference (before network adjustments)
|
||||
let userPreferredQuality = settingsManager?.preferredQuality ?? .auto
|
||||
@@ -1932,7 +1931,6 @@ final class PlayerService {
|
||||
let muxedStreams = streams.filter { stream in
|
||||
let format = StreamFormat.detect(from: stream)
|
||||
guard supportedFormats.contains(format) else { return false }
|
||||
if format == .dash && !dashEnabled { return false }
|
||||
// Only include HLS/DASH if they have video (audio-only HLS/DASH should be treated as audio streams)
|
||||
if format == .hls || format == .dash {
|
||||
return !stream.isAudioOnly
|
||||
@@ -1972,7 +1970,7 @@ final class PlayerService {
|
||||
LoggingService.shared.debug("Stream selection: Using HLS for live stream", category: .player)
|
||||
return (hlsStream, nil)
|
||||
}
|
||||
if dashEnabled, let dashStream = muxedStreams.first(where: { StreamFormat.detect(from: $0) == .dash }) {
|
||||
if let dashStream = muxedStreams.first(where: { StreamFormat.detect(from: $0) == .dash }) {
|
||||
LoggingService.shared.debug("Stream selection: Using DASH for live stream", category: .player)
|
||||
return (dashStream, nil)
|
||||
}
|
||||
@@ -2065,16 +2063,13 @@ final class PlayerService {
|
||||
filteredMuxed = muxedStreams
|
||||
}
|
||||
|
||||
// Sort: prefer non-HLS/DASH (progressive) formats, then by resolution
|
||||
// Sort: prefer progressive formats, then HLS, and only fall back to DASH as a last
|
||||
// resort (DASH should never be chosen when any other format is available).
|
||||
let sortedMuxed = filteredMuxed.sorted { s1, s2 in
|
||||
let format1 = StreamFormat.detect(from: s1)
|
||||
let format2 = StreamFormat.detect(from: s2)
|
||||
let isAdaptive1 = format1 == .hls || format1 == .dash
|
||||
let isAdaptive2 = format2 == .hls || format2 == .dash
|
||||
|
||||
// Prefer progressive formats for non-live content
|
||||
if isAdaptive1 != isAdaptive2 {
|
||||
return !isAdaptive1 // non-adaptive (false) comes first
|
||||
let rank1 = muxedFormatRank(StreamFormat.detect(from: s1))
|
||||
let rank2 = muxedFormatRank(StreamFormat.detect(from: s2))
|
||||
if rank1 != rank2 {
|
||||
return rank1 < rank2
|
||||
}
|
||||
return (s1.resolution ?? .p360) > (s2.resolution ?? .p360)
|
||||
}
|
||||
@@ -2091,6 +2086,17 @@ final class PlayerService {
|
||||
return nil
|
||||
}
|
||||
|
||||
/// Ranks muxed formats for fallback selection (lower = preferred).
|
||||
/// Progressive formats win, then HLS; DASH is the last resort and is only
|
||||
/// selected when it is the only format available.
|
||||
private func muxedFormatRank(_ format: StreamFormat) -> Int {
|
||||
switch format {
|
||||
case .dash: return 2
|
||||
case .hls: return 1
|
||||
default: return 0 // progressive
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns codec priority for video streams (higher = better).
|
||||
/// Prefers hardware-decodable codecs for battery efficiency.
|
||||
private func videoCodecPriority(_ codec: String?) -> Int {
|
||||
|
||||
@@ -667,12 +667,11 @@ private struct PlayerSheetsModifier: ViewModifier {
|
||||
private var qualitySelectorSheet: some View {
|
||||
if let playerService {
|
||||
let supportedFormats = playerService.currentBackendType.supportedFormats
|
||||
let dashEnabled = appEnvironment?.settingsManager.dashEnabled ?? false
|
||||
QualitySelectorView(
|
||||
streams: playerService.availableStreams.filter { stream in
|
||||
let format = StreamFormat.detect(from: stream)
|
||||
// Filter out DASH streams if disabled in settings
|
||||
if format == .dash && !dashEnabled {
|
||||
// DASH is never offered for manual selection
|
||||
if format == .dash {
|
||||
return false
|
||||
}
|
||||
return supportedFormats.contains(format)
|
||||
|
||||
@@ -143,13 +143,13 @@ struct TVPlayerView: View {
|
||||
@ViewBuilder
|
||||
private var qualityPanelContent: some View {
|
||||
if let playerService {
|
||||
let dashEnabled = appEnvironment?.settingsManager.dashEnabled ?? false
|
||||
let supportedFormats = playerService.currentBackendType.supportedFormats
|
||||
|
||||
QualitySelectorView(
|
||||
streams: playerService.availableStreams.filter { stream in
|
||||
let format = StreamFormat.detect(from: stream)
|
||||
if format == .dash && !dashEnabled {
|
||||
// DASH is never offered for manual selection
|
||||
if format == .dash {
|
||||
return false
|
||||
}
|
||||
return supportedFormats.contains(format)
|
||||
|
||||
@@ -206,13 +206,6 @@ struct AdvancedSettingsView: View {
|
||||
Label(String(localized: "settings.advanced.mpv.edl"), systemImage: "arrow.trianglehead.merge")
|
||||
}
|
||||
|
||||
Toggle(isOn: Binding(
|
||||
get: { settingsManager.dashEnabled },
|
||||
set: { settingsManager.dashEnabled = $0 }
|
||||
)) {
|
||||
Label(String(localized: "settings.playback.dash"), systemImage: "bolt.horizontal")
|
||||
}
|
||||
|
||||
#if os(tvOS)
|
||||
NavigationLink {
|
||||
TVSidebarDetailContainer(
|
||||
|
||||
Reference in New Issue
Block a user