diff --git a/backend/__pycache__/config.cpython-310.pyc b/backend/__pycache__/config.cpython-310.pyc index 9327efc..cd0b255 100644 Binary files a/backend/__pycache__/config.cpython-310.pyc and b/backend/__pycache__/config.cpython-310.pyc differ diff --git a/backend/__pycache__/downloader.cpython-310.pyc b/backend/__pycache__/downloader.cpython-310.pyc index 71f9947..665b4d1 100644 Binary files a/backend/__pycache__/downloader.cpython-310.pyc and b/backend/__pycache__/downloader.cpython-310.pyc differ diff --git a/backend/downloader.py b/backend/downloader.py index d4abd16..d846808 100644 --- a/backend/downloader.py +++ b/backend/downloader.py @@ -1,30 +1,52 @@ -import subprocess +import yt_dlp from pathlib import Path from config import settings def is_playlist(query: str) -> bool: return "playlist" in query or "list=" in query +def is_youtube_url(query: str) -> bool: + return query.startswith("http") + +def duration_range_filter(min_seconds, max_seconds): + def _filter(info, *, incomplete): + duration = info.get('duration') + if duration: + if duration < min_seconds: + return f"Skipping: {info.get('title')} is shorter than {min_seconds//60} minutes" + if duration > max_seconds: + return f"Skipping: {info.get('title')} is longer than {max_seconds//60} minutes" + return _filter + def download_song(query: str): Path(settings.MUSIC_DIR).mkdir(parents=True, exist_ok=True) - output_template = f"{settings.MUSIC_DIR}/%(title)s.%(ext)s" - command = [ - "yt-dlp", - f"{query if query.startswith('http') else f'ytsearch1:{query}'}", - "--extract-audio", - "--audio-format", "mp3", - "--add-metadata", - "--output", output_template, - "--verbose" - ] - # Only add --no-playlist for search queries - if not is_playlist(query) and not query.startswith("http"): - command.append("--no-playlist") - print("Running command:", " ".join(command)) - result = subprocess.run(command, capture_output=True, text=True) - print("STDOUT:", result.stdout) - print("STDERR:", result.stderr) - if result.returncode != 0: - raise Exception(f"yt-dlp failed: {result.stderr}") + if is_youtube_url(query): + yt_query = query + noplaylist = False + elif is_playlist(query): + yt_query = query + noplaylist = False + else: + yt_query = f"ytsearch10:{query}" # Always search for 10 results for any artist/song query + noplaylist = True + + ydl_opts = { + 'format': 'bestaudio/best', + 'outtmpl': f"{settings.MUSIC_DIR}/%(title)s.%(ext)s", + 'postprocessors': [{ + 'key': 'FFmpegExtractAudio', + 'preferredcodec': 'mp3', + }, { + 'key': 'FFmpegMetadata', + }], + 'match_filter': duration_range_filter(2 * 60, 9 * 60), # 2 to 9 minutes + 'noplaylist': noplaylist, + 'quiet': False, + 'verbose': True, + } + + print("yt-dlp options:", ydl_opts) + with yt_dlp.YoutubeDL(ydl_opts) as ydl: + result = ydl.download([yt_query]) return {"downloaded": "Check music folder for downloaded files"} \ No newline at end of file