From fe0f8241ff0dc2382d2065b732244594300f3e6a Mon Sep 17 00:00:00 2001 From: oop7 <110548351+oop7@users.noreply.github.com> Date: Tue, 28 Apr 2026 12:55:46 +0300 Subject: [PATCH] Improve playlist format selection and resolution When downloading playlists, avoid reusing a specific format_id from the first item (which can fail for subsequent videos). For audio-only playlists, use yt-dlp's bestaudio fallback; for video playlists, respect a provided resolution by extracting the height and applying -S res:, otherwise fall back to bestvideo+bestaudio/best. Invalid resolution strings are caught and logged, and revert to the dynamic best-quality fallback. --- ytsage/core/ytsage_downloader.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/ytsage/core/ytsage_downloader.py b/ytsage/core/ytsage_downloader.py index 3df0fe7..6f5b7b2 100644 --- a/ytsage/core/ytsage_downloader.py +++ b/ytsage/core/ytsage_downloader.py @@ -242,7 +242,29 @@ class DownloadThread(QThread): logger.debug(f"Using {self.concurrent_fragments} concurrent connections") # Format selection strategy - use format ID if provided or fallback to resolution - if self.format_id: + if self.is_playlist: + # For playlists, specific format_id from the first video often fails for subsequent videos. + # Instead, we rely on dynamic fallback/resolution limits. + if self.is_audio_only: + # For audio-only playlist, let yt-dlp pick best audio. + cmd.extend(["-f", "bestaudio/best"]) + logger.debug(f"Playlist mode: using dynamic best audio fallback instead of format_id") + else: + # If a specific resolution is given, limit to it. Otherwise, select the overall best. + # The resolution might be e.g. "1920x1080" or "1080". We want the height. + try: + if self.resolution and self.resolution != "default": + res_str = str(self.resolution) + h = min(map(int, res_str.split('x'))) if 'x' in res_str else int(res_str) + cmd.extend(["-S", f"res:{h}"]) + logger.debug(f"Playlist mode: using resolution limiter -S res:{h}") + else: + cmd.extend(["-f", "bestvideo+bestaudio/best"]) + logger.debug("Playlist mode: using dynamic best quality overall") + except ValueError: + cmd.extend(["-f", "bestvideo+bestaudio/best"]) + logger.debug("Playlist mode: invalid resolution string, using dynamic best quality overall") + elif self.format_id: clean_format_id: str = self.format_id.split("-drc")[0] if "-drc" in self.format_id else self.format_id # If the selected format is audio-only, pass it directly.