import yt_dlp import os import shutil import re def sanitize_filename(name): return re.sub(r'[\\/*?:"<>|@#$%^&+=~`\';]', '', name).strip() def get_download_path(): paths = [ '/mnt/sdcard/Music', '/storage/emulated/0/Music', '/sdcard/Music', os.path.join(os.environ.get('HOME', ''), 'Music'), os.path.join(os.getcwd(), 'music') ] for path in paths: if os.path.exists(path): return path os.makedirs(paths[-1], exist_ok=True) return paths[-1] def load_music_list(): music_list = [] with open('musiclist.txt', 'r') as f: for line in f: line = line.strip() if not line: continue try: parts = line.split('---') music_list.append({ 'name': sanitize_filename(parts[0].strip()), 'id': parts[1].strip(), 'provider': parts[2].strip().upper() }) except IndexError: print(f"Invalid line format: {line}") return music_list def download_track(music, download_path): base_url = f"https://{'music.' if music['provider'] == 'YTM' else ''}youtube.com/watch?v={music['id']}" output_path = os.path.join(download_path, f"{music['name']}.opus") if os.path.exists(output_path): print(f"Skipping existing track: {music['name']}") return ytdl_opts = { 'format': 'bestaudio/best', 'outtmpl': f"{music['name']}.%(ext)s", 'postprocessors': [ {'key': 'FFmpegExtractAudio', 'preferredcodec': 'opus'}, {'key': 'FFmpegMetadata'}, {'key': 'EmbedThumbnail'} ], 'writethumbnail': True, 'quiet': True, 'no_warnings': True, 'logger': MyLogger() } try: with yt_dlp.YoutubeDL(ytdl_opts) as ydl: ydl.download([base_url]) shutil.move(f"{music['name']}.opus", output_path) print(f"Downloaded: {music['name']}") except Exception as e: print(f"Error downloading {music['name']}: {str(e)}") class MyLogger: def debug(self, msg): pass def warning(self, msg): pass def error(self, msg): print(msg) if __name__ == "__main__": download_path = get_download_path() print(f"Download location: {download_path}") music_list = load_music_list() total = len(music_list) for index, music in enumerate(music_list, 1): print(f"\nProcessing track {index}/{total}") download_track(music, download_path)