Files
ytaml/ytaml.py
T

193 lines
3.5 KiB
Python

import os
import sys
import json
import yt_dlp
g_OUTPUT_FOLDER = "cd_audio"
def generate_ytdl_opts(outtmpl: str, metadata_artist: str = "", metadata_title: str = ""):
return {
"format": "bestaudio/best",
"noplaylist": True,
"outtmpl": outtmpl,
"postprocessors": [
{
"key": "FFmpegExtractAudio",
"preferredcodec": "wav",
}
],
"postprocessor_args": [
"-ar", "44100",
"-ac", "2",
"-metadata", f"artist={metadata_artist}",
"-metadata", f"title={metadata_title}",
],
"ignoreerrors": True,
}
def download_playlist_for_cd(playlist_url: str):
ytdl_opts = generate_ytdl_opts(
os.path.join(g_OUTPUT_FOLDER, "%(playlist_index)s - %(title)s.%(ext)s")
)
print(f"Downloading audio optimized for CD burning: {playlist_url}")
with yt_dlp.YoutubeDL(ytdl_opts) as ytdl:
ytdl.download([playlist_url])
print("\nDownload complete! Import these .wav files directly into your CD burner.")
def download_single_video(url, song_num, artist, title):
ytdl_opts = generate_ytdl_opts(
os.path.join(g_OUTPUT_FOLDER, f"{song_num} - {artist} - {title}.%(ext)s"),
artist, title
)
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
def print_help():
print("-h print help and exit")
print("-f <filename> select a file (required)")
print("-a download all")
print("-d <album> download a specific album")
def parse_args(argv):
class Ret:
file = None
downloads = None
ret = Ret()
cache_arg_count = len(argv)
arg_idx = 1
while arg_idx < cache_arg_count:
if argv[arg_idx] == "-h":
print_help()
exit(1)
elif argv[arg_idx] == "-f":
if arg_idx + 1 >= cache_arg_count:
raise ValueError("-f <filename> - is missing the filename")
ret.file = argv[arg_idx + 1]
arg_idx += 2
continue
elif argv[arg_idx] == "-a":
if ret.downloads != None:
raise ValueError("Cannot use -a twice, or in combination with -d")
ret.downloads = ""
arg_idx += 1
continue
elif argv[arg_idx] == "-d":
if ret.downloads != None:
raise ValueError("Cannot use -d twice, or in combination with -a")
if arg_idx + 1 >= cache_arg_count:
raise ValueError("-d <album> - is missing the album name")
ret.downloads = argv[arg_idx + 1]
arg_idx += 2
continue
else:
print_help()
exit(2)
return ret
if __name__ == "__main__":
config = parse_args(sys.argv)
if not os.path.exists(g_OUTPUT_FOLDER):
os.makedirs(g_OUTPUT_FOLDER)
data = parse_file(config.file)
for album in data:
if not (config.downloads == "" or config.downloads == album.album):
continue
print(f"Band: {album.artist}")
print(f"Album: {album.album}")
for video in album.tracks:
print(f"\tTrack {video.track}: {video.title}")
download_single_video(
video.url,
video.track,
f"{album.artist} - {album.album}",
video.title
)