Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions spotdl/download/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
from spotdl.utils.m3u import gen_m3u_files
from spotdl.utils.metadata import MetadataError, embed_metadata
from spotdl.utils.search import gather_known_songs, reinit_song, songs_from_albums
from spotdl.utils.youtube_utils import detect_youtube_premium

__all__ = [
"AUDIO_PROVIDERS",
Expand Down Expand Up @@ -197,6 +198,16 @@ def __init__(

# Initialize audio providers
self.audio_providers: List[AudioProvider] = []

# Extract cookie file path once
cookie_file_path = self.settings.get("cookie_file")

# Detect Premium only once if YouTube is an audio provider
if cookie_file_path and any(
"youtube" in ap.lower() for ap in self.settings["audio_providers"]
):
detect_youtube_premium(cookie_file_path)

for audio_provider in self.settings["audio_providers"]:
audio_class = AUDIO_PROVIDERS.get(audio_provider)
if audio_class is None:
Expand Down Expand Up @@ -675,6 +686,21 @@ def search_and_download( # pylint: disable=R0911
display_progress_tracker.yt_dlp_progress_hook
)

# Premium format selection
if "youtube" in self.settings["audio_providers"][0].lower():
try:
from spotdl.utils.youtube_utils import get_best_audio_format

premium_format_string = get_best_audio_format(
download_url, self.settings.get("cookie_file")
)
self.settings["yt_dlp_args"]["format"] = premium_format_string

except Exception as e:
logger.debug(
f"Failed to determine Premium format for {download_url}: {e}"
)

download_info = audio_downloader.get_download_metadata(
download_url, download=True
)
Expand Down
53 changes: 53 additions & 0 deletions spotdl/providers/audio/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Youtube module for downloading and searching songs.
"""

# import yt_dlp
import logging
from typing import Any, Dict, List, Optional

from pytube import Search
Expand All @@ -11,6 +13,51 @@
from spotdl.providers.audio.base import AudioProvider
from spotdl.types.result import Result

logger = logging.getLogger("spotdl")


def get_best_audio_format(video_url: str, cookies_path: Optional[str] = None) -> str:
"""
Returns the best audio format string for yt_dlp based on Premium availability.
If Premium formats (high-quality opus) are found, they are prioritized.
"""
ydl_opts = {
"quiet": True,
"skip_download": True,
"nocheckcertificate": True,
}

if cookies_path:
ydl_opts["cookiefile"] = cookies_path

try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(video_url, download=False)
formats = info.get("formats", [])

# Look for premium-level audio (opus codec ≥160kbps)
premium_formats = [
f
for f in formats
if f.get("acodec") == "opus" and f.get("abr", 0) >= 160
]

if premium_formats:
best = max(premium_formats, key=lambda f: f.get("abr", 0))
logger.info(
f"YouTube Premium detected — downloading high-quality audio ({best.get('abr')}kbps)."
)
return f"{best['format_id']}/bestaudio/best"

# Fallback to normal formats
logger.info("Regular YouTube account — downloading standard audio.")
return "bestaudio/best"

except Exception as e:
logger.debug(f"Premium format detection failed for {video_url}: {e}")
return "bestaudio/best"


__all__ = ["YouTube"]


Expand Down Expand Up @@ -67,6 +114,11 @@ def get_results(
except Exception:
views = 0

# Dynamically choose best format
format_string = get_best_audio_format(
result.watch_url, getattr(self, "cookie_file", None)
)

results.append(
Result(
source=self.name,
Expand All @@ -78,6 +130,7 @@ def get_results(
search_query=search_term,
views=views,
result_id=result.video_id,
additional_info={"format_string": format_string},
)
)

Expand Down
102 changes: 102 additions & 0 deletions spotdl/utils/youtube_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import logging
from typing import Optional

import yt_dlp

# Use the project logger configured via init_logging
logger = logging.getLogger("spotdl")


def get_best_audio_format(video_url: str, cookies_path: Optional[str] = None) -> str:
"""
Determine the best YouTube audio format available for a given video.
If Premium formats (e.g., high-bitrate Opus) are available using the cookies,
return the appropriate yt_dlp format string to download them.
Otherwise, return the default 'bestaudio/best'.

Args:
video_url (str): The YouTube video URL.
cookies_path (Optional[str]): Path to cookies.txt file (optional).

Returns:
str: The best audio format string for yt_dlp.
"""

logger.info(f"[YT Premium Detection] Checking formats for: {video_url}")

ydl_opts = {
"quiet": True,
"skip_download": True,
"nocheckcertificate": True,
}

if cookies_path:
ydl_opts["cookiefile"] = cookies_path

try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(video_url, download=False)
formats = info.get("formats", [])

if not formats:
logger.debug("No formats found for video.")
return "bestaudio/best"

# Look for premium-level formats (high-bitrate Opus)
premium_formats = [
f
for f in formats
if f.get("acodec") == "opus" and f.get("abr", 0) >= 160
]

if premium_formats:
best = max(premium_formats, key=lambda f: f.get("abr", 0))
logger.info(
f"YouTube Premium detected — downloading {best.get('abr')}kbps Opus format."
)
return f"{best['format_id']}/bestaudio/best"

# Fallback to standard formats
logger.info("Regular YouTube account — downloading standard audio.")
return "bestaudio/best"

except Exception as e:
logger.debug(f"Premium detection failed for {video_url}: {e}")
return "bestaudio/best"


def detect_youtube_premium(cookies_path: str) -> bool:
"""
Detect if the provided YouTube cookies belong to a Premium account.
Returns True if Premium-quality formats appear available, False otherwise.
"""

test_url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
ydl_opts = {
"quiet": True,
"skip_download": True,
"nocheckcertificate": True,
"cookiefile": cookies_path,
}

try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(test_url, download=False)
formats = info.get("formats", [])

premium_formats = [
f
for f in formats
if f.get("acodec") == "opus" and f.get("abr", 0) >= 160
]

if premium_formats:
best = max(premium_formats, key=lambda f: f.get("abr", 0))
logger.info(
f"YouTube Premium detected — premium audio available ({best.get('abr')}kbps opus)."
)
return True
except Exception as exc:
logger.debug(f"Premium detection check failed: {exc}")

return False