import os import sys import json import yt_dlp def download_playlist_for_cd(playlist_url: str, output_folder: str = "cd_audio"): """Downloads YouTube audio directly into 44.1kHz 16-bit WAV files ideal for burning directly to Audio CDs without secondary re-encoding loss. """ if not os.path.exists(output_folder): os.makedirs(output_folder) ydl_opts = { # Grab best audio stream available "format": "bestaudio/best", # Prefix with track index (01, 02...) so CD track order matches playlist order "outtmpl": os.path.join(output_folder, "%(playlist_index)s - %(title)s.%(ext)s"), "postprocessors": [ { "key": "FFmpegExtractAudio", "preferredcodec": "wav", # Lossless format native to CD Burning } ], # Enforce Red Book CD Standard audio resampling (44.1 kHz) "postprocessor_args": [ "-ar", "44100", # Set sample rate to 44.1 kHz (CD Standard) "-ac", "2", # Force 2 channels (Stereo) ], "ignoreerrors": True, } print(f"Downloading audio optimized for CD burning: {playlist_url}") with yt_dlp.YoutubeDL(ydl_opts) as ydl: ydl.download([playlist_url]) print("\nDownload complete! Import these .wav files directly into your CD burner.") def download_single_video(url, song_num, artist, title): output_folder = "cd_audio" if not os.path.exists(output_folder): os.makedirs(output_folder) ytdl_opts = { "format": "bestaudio/best", "noplaylist": True, "outtmpl": os.path.join(output_folder, f"{song_num} - {artist} - {title}.%(ext)s"), "postprocessors": [ { "key": "FFmpegExtractAudio", "preferredcodec": "wav", } ], "postprocessor_args": [ "-ar", "44100", # Set sample rate to 44.1 kHz (CD Standard) "-ac", "2", # Force 2 channels (Stereo) "-metadata", f"artist={artist}", "-metadata", f"title={title}", ], "ignoreerrors": True, } with yt_dlp.YoutubeDL(ytdl_opts) as ytdl: ytdl.download([url]) def parse_file(filename): class Track: def __init__(self, track: int, title: str, url: str): self.track = track self.title = title self.url = url class Album: def __init__(self, artist: str, album: str): self.artist = artist self.album = album self.tracks = [] def add_track(self, track: Track): self.tracks.append(track) with open(filename, "r") as file: data = json.load(file) albums = [] for album in data: try: new_album = Album( album["artist"], album["album"]) for video in album["tracks"]: new_album.add_track(Track( video["track"], video["title"], video["url"] )) except KeyError as e: print(e) continue albums.append(new_album) return albums if __name__ == "__main__": if len(sys.argv) == 1: url = input("Enter YouTube playlist URL: ").strip() if url: download_playlist_for_cd(url) else: data = parse_file(" ".join(sys.argv[1:])) for album in data: print(f"Band: {album.artist}") print(f"Album: {album.album}") for video in album.tracks: print(f"\tTrack {video.track}: {video.title}") if album.album == "Even In Arcadia": download_single_video( video.url, video.track, f"{album.artist} - {album.album}", video.title )