#!/usr/bin/env python3 import json # Can't remember what I needed this for... Maybe checking if song already # exists? # import musicpd import music_tag import os import youtube_dl from ytmusicapi import YTMusic DEBUG = True # Includes the format characters YOUTUBE_MUSIC_URL = "https://music.youtube.com/watch?v={}" """ How the albums will be formatted { 'id': { 'name': '', 'tracks': [ { 'id': '', 'name': '' } ], "thumbnail_url": '', "is_thumbnail_downloaded": False, "thumbnail_filename": '', } } """ ALBUMS = {} def create_downloader(music_directory, cookies): audio_options = { 'format': 'mp3/bestaudio/best', 'cookiefile': cookies, 'outtmpl': os.path.join(music_directory, '%(title)s.%(ext)s'), 'postprocessors': [ { 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '192', }, {'key': 'FFmpegMetadata'}, ], 'writeinfojson': True, 'quiet': not DEBUG } def write_metadata_to_song_file(filename, metadata): file = music_tag.load_file(filename) file['name'] = metadata['title'] file['artist'] = metadata['artist'] file['album'] = metadata['album'] file['year'] = metadata['year'] file.save() if __name__ == "__main__": app = YTMusic('../headers_auth.json') song_limit = 25 all_raw_song_data = app.get_library_songs(limit=song_limit, order='a_to_z') if DEBUG: with open('raw_song_data.json', 'w') as f: f.write(json.dumps(all_raw_song_data)) all_parsed_songs = [] for raw_song in all_raw_song_data: song_id = raw_song['videoId'] album_id = raw_song['album']['id'] if album_id not in ALBUMS.keys(): raw_album = app.get_album(album_id) ALBUMS[album_id] = { 'name': raw_album['title'], 'tracks': [{'title': song['title'], 'id': song['videoId'], 'track_num': index + 1} for index, song in enumerate(raw_album['tracks'])], 'year': raw_album['year'], # TODO: Add thumbnail_url } album = ALBUMS[album_id] track_num = None for track in ALBUMS[album_id]['tracks']: if track['id'] == song_id: track_num = track['track_num'] parsed_song = { 'id': raw_song['videoId'], 'title': raw_song['title'], 'artists': [artist['name'] for artist in raw_song['artists']], 'album': raw_song['album']['name'], 'track': track_num, 'url': YOUTUBE_MUSIC_URL.format(raw_song['videoId']), 'year': album['year'] } all_parsed_songs.append(parsed_song) if DEBUG: with open('parsed_album_data.json', 'w') as f: f.write(json.dumps({'albums': ALBUMS})) with open('parsed_song_data.json', 'w') as f: f.write(json.dumps({'songs': all_parsed_songs})) # music_directory = os.path.join(os.path.expanduser("~"), "Music") music_directory = './music' # TODO: Can you use the cookies from YTMusic here # cookies = os.path.join(os.path.expanduser("~"), "cookies.txt") cookies = './cookies.txt' ytdl = create_downloader(music_directory, cookies) failed_songs = [] for song in all_parsed_songs: try: ytdl.extract_info(song['url'], download=True) except Exception as ex: print(ex) print("Could not download: {}".format((song))) failed_songs.append(song) files = get_all_files(music_directory)