diff --git a/unshackle/commands/dl.py b/unshackle/commands/dl.py index 9e59c66..b62f004 100644 --- a/unshackle/commands/dl.py +++ b/unshackle/commands/dl.py @@ -1663,7 +1663,7 @@ class dl: ] # Apply hybrid selection to HDR10+DV tracks - hybrid_filter = title.tracks.select_hybrid(hybrid_candidate_tracks, quality) + hybrid_filter = title.tracks.select_hybrid(hybrid_candidate_tracks, quality, worst=worst) hybrid_selected = list(filter(hybrid_filter, hybrid_candidate_tracks)) if non_hybrid_ranges and non_hybrid_tracks: @@ -1718,12 +1718,14 @@ class dl: if not quality: best_resolution = max((v.height for v in hybrid_candidate_tracks), default=None) if best_resolution: - hybrid_filter = title.tracks.select_hybrid(hybrid_candidate_tracks, [best_resolution]) + hybrid_filter = title.tracks.select_hybrid( + hybrid_candidate_tracks, [best_resolution], worst=worst + ) hybrid_selected = list(filter(hybrid_filter, hybrid_candidate_tracks)) else: hybrid_selected = [] else: - hybrid_filter = title.tracks.select_hybrid(hybrid_candidate_tracks, quality) + hybrid_filter = title.tracks.select_hybrid(hybrid_candidate_tracks, quality, worst=worst) hybrid_selected = list(filter(hybrid_filter, hybrid_candidate_tracks)) # For non-hybrid ranges, apply Cartesian product selection diff --git a/unshackle/core/tracks/tracks.py b/unshackle/core/tracks/tracks.py index 76136ff..08d0ec2 100644 --- a/unshackle/core/tracks/tracks.py +++ b/unshackle/core/tracks/tracks.py @@ -316,7 +316,7 @@ class Tracks: new_tracks.attachments = list(self.attachments) return new_tracks - def select_hybrid(self, tracks, quality): + def select_hybrid(self, tracks, quality, worst: bool = False): # Prefer HDR10+ over HDR10 as the base layer (preserves dynamic metadata) base_ranges = (Video.Range.HDR10P, Video.Range.HDR10) base_tracks = [] @@ -327,12 +327,13 @@ class Tracks: if base_tracks: break + pick = min if worst else max base_selected = [] for res in quality: candidates = [v for v in base_tracks if v.height == res or int(v.width * 9 / 16) == res] if candidates: - best = max(candidates, key=lambda v: v.bitrate) - base_selected.append(best) + chosen = pick(candidates, key=lambda v: v.bitrate) + base_selected.append(chosen) dv_tracks = [v for v in tracks if v.range == Video.Range.DV] lowest_dv = min(dv_tracks, key=lambda v: v.height) if dv_tracks else None