diff --git a/examples/music_audio_config.yaml b/examples/music_audio_config.yaml deleted file mode 100644 index 7338a67d..00000000 --- a/examples/music_audio_config.yaml +++ /dev/null @@ -1,194 +0,0 @@ -# This config builds presets to download and format the following use-cases: -# - YouTube -# - Songs -# - From a single video -# - Albums -# - From a video, where each song is represented by chapters -# - From a playlist where each video is a song on the album -# - Discographies -# - From a channel or a channel's set of playlists -# - Bandcamp -# - Track, Album, Artist URL as a Discography -# - Soundcloud -# - Track, Album, Artist URL as a Discography -# -# All files will look like: -# -# music_directory/ -# Artist/ -# [2022] Some Single/ -# 01 - Some Single.mp3 -# folder.jpg -# [2023] Latest Album/ -# 01 - Track Title.mp3 -# 02 - Another Track.mp3 -# folder.jpg -# -# The idea is to format files under music_directory as `Artist/Album/Song`. Singles that do not -# belong to an album will be represented like albums with a single track. -# -# Each file will be properly tagged regardless of file extension (suppers flac, ogg, mp3, etc) -# and should show up nicely in music players that take advantage of tags. -configuration: - working_directory: '.ytdl-sub-downloads' - umask: "002" - -presets: - - # The `base` preset that represents how all files will be structured after downloading. - # Every other preset afterwards will inherit this preset. - base: - # Store all music under our music_directory (to be set as an override variable). - # Store each resulting file with its full track path, and treat thumbnails as the album covers. - # - # Maintain a download archive. This will produce a hidden file in your music directory - # containing an archive of all audio previously downloaded. This makes it so we do not - # re-download files we already have. - output_options: - output_directory: "{music_directory}" - file_name: "{track_full_path}" - thumbnail_name: "{album_cover_path}" - maintain_download_archive: True - - # Set break_on_existing to True. This will stop fetching any more metadata once we - # hit a video/audio that we already have downloaded. - ytdl_options: - break_on_existing: True - - # Extract any audio from files using this codec and quality. - audio_extract: - codec: "mp3" - quality: 320 - - # Set these music tags on every resulting audio file. - # It is recommended to keep most of this as-is, and use override - # variables to set them to be what you want. - music_tags: - artist: "{track_artist}" - artists: "{track_artist}" - albumartist: "{track_artist}" - albumartists: "{track_artist}" - title: "{track_title}" - album: "{track_album}" - track: "{track_number}" - tracktotal: "{track_total}" - year: "{track_year}" - genre: "{track_genre}" - - # Optionally embed the thumbnail into the track - embed_thumbnail: False - - # For every configurable field, make it an override variable, - # so we can carefully tune different use-cases by only modifying override variables. - overrides: - # Track Overrides. By default, set overrides to make each song its own album - track_title: "{title}" - track_album: "{title}" - track_artist: "{channel}" - track_number: "1" - track_number_padded: "01" - track_total: "1" - track_year: "{upload_year}" - track_genre: "Unset" - # Filename Overrides - track_file_name: "{track_number_padded} - {track_title_sanitized}.{ext}" - album_file_name: "folder.{thumbnail_ext}" - # Directory Name Overrides - music_directory: "OVERRIDE THIS WITH YOUR MUSIC DIRECTORY" - artist_dir: "{track_artist_sanitized}" - album_dir: "[{track_year}] {track_album_sanitized}" - # Full Filepath Overrides - track_full_path: "{artist_dir}/{album_dir}/{track_file_name}" - album_cover_path: "{artist_dir}/{album_dir}/{album_file_name}" - -#################################################################################################### - - # Make the 'single` preset accept a single URL using the override variable 'url' - # Each audio file will reside in its own album. - single: - # Inherit from `base` - preset: "base" - - download: - url: "{url}" - -#################################################################################################### - - # Make the 'albums_from_playlists' preset format audio files to reside under albums, where - # each album is a playlist. If a file downloaded using this preset is not part of a playlist, - # it will default to how it'd look as a `single`. - albums_from_playlists: - # Inherit from single - preset: "single" - - # Override various track properties using playlist variables. - overrides: - track_album: "{playlist_title}" - track_number: "{playlist_index}" - track_number_padded: "{playlist_index_padded}" - track_total: "{playlist_count}" - track_year: "{playlist_max_upload_year}" - -#################################################################################################### - - # Make the 'albums_from_chapters' preset format audio files to reside under an album, where the - # video itself is an album containing all the songs in it represented by chapters. - albums_from_chapters: - # Inherit from single - preset: "single" - - # Embed chapters if present. If no chapters are present, allow parsing comments that contain - # timestamps to each song, and use those as chapters. - chapters: - embed_chapters: True - allow_chapters_from_comments: True - - # Split each file by its chapters. If a file does not have chapters, simply 'pass' on it and - # process the next audio/video file. - split_by_chapters: - when_no_chapters: "pass" - - # Override various track properties using chapter variables. - overrides: - track_title: "{chapter_title}" # Chapter title is the track title - track_album: "{title}" # Video's title is the album title - track_number: "{chapter_index}" - track_number_padded: "{chapter_index_padded}" - track_total: "{chapter_count}" - -#################################################################################################### - - # Make the 'soundcloud_discography' preset specially made for ripping SoundCloud artists. - # We will use the 'multi_url' approach to download both albums and non-album tracks - soundcloud_discography: - preset: "base" - - # Download using the multi_url strategy - download: - # The first URL will be all the artist's tracks. - # Treat these as singles - an album with a single track - - url: "{sc_artist_url}/tracks" - variables: - sc_track_album: "{title}" - sc_track_number: "1" - sc_track_number_padded: "01" - sc_track_total: "1" - sc_track_year: "{upload_year}" - # Set the second URL to the artist's albums. If a track belongs to both - # to an album and tracks (in the URL above), it will resolve to this - # URL and include the album metadata we set below. - - url: "{sc_artist_url}/albums" - variables: - sc_track_album: "{playlist_title}" - sc_track_number: "{playlist_index}" - sc_track_number_padded: "{playlist_index_padded}" - sc_track_total: "{playlist_count}" - sc_track_year: "{playlist_max_upload_year}" - - # Override various track properties using playlist variables. - overrides: - track_album: "{sc_track_album}" - track_number: "{sc_track_number}" - track_number_padded: "{sc_track_number_padded}" - track_total: "{sc_track_total}" - track_year: "{sc_track_year}" \ No newline at end of file diff --git a/examples/music_audio_subscriptions.yaml b/examples/music_audio_subscriptions.yaml index e627fa9d..7f4622d9 100644 --- a/examples/music_audio_subscriptions.yaml +++ b/examples/music_audio_subscriptions.yaml @@ -1,137 +1,46 @@ -# Define any number of subscriptions in a single file, or use multiple -# files to organize (i.e by use-case, website, genre, etc) +# Files will be stored in the form of: # -# Each example show-cases every use case: -# - YouTube -# - Songs -# - From a single video -# - Albums -# - From a video, where each song is represented by chapters -# - From a playlist where each video is a song on the album -# - Discographies -# - From a channel or a channel's set of playlists -# - Bandcamp -# - Track, Album, Artist URL as a Discography -# - Soundcloud -# - Track, Album, Artist URL as a Discography -# -#################################################################################################### -# YOUTUBE - PLAYLIST OF ALBUMS -# See https://www.youtube.com/playlist?list=PLBsm_SagFMmdWnCnrNtLjA9kzfrRkto4i -# -# Downloads the GameChops Albums' playlist. Each video in the playlist is an album with -# chapters representing songs. -game_chops: - preset: "albums_from_chapters" +# music_directory/ +# Artist/ +# [2022] Some Single/ +# 01 - Some Single.mp3 +# folder.jpg +# [2023] Latest Album/ +# 01 - Track Title.mp3 +# 02 - Another Track.mp3 +# folder.jpg - # Perform regex to extract title from the chapter's title to not include the track number. - # Configuring this hard is a bit overkill, but I'm a perfectionist :-) - regex: - from: - chapter_title: - match: - - "^\\d+\\.\\.(.*)" # Captures 'title' from '1..title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{chapter_title}" - - # Explicitly set the URL, track artist, and genre. - # Override various track properties using the regex variables we extracted. +# Overrides to the prebuilt presets +__preset__: overrides: - url: "https://www.youtube.com/playlist?list=PLBsm_SagFMmdWnCnrNtLjA9kzfrRkto4i" - track_artist: "GameChops" - track_genre: "Lofi" - track_title: "{captured_track_title}" + music_directory: "/music" +# Supports downloading YouTube /releases tab. Also works for any playlist (or playlist of playlists) +# where each video is a single track. +YouTube Releases: + = Jazz: # Sets genre to "Jazz" + "Lester Young": "https://www.youtube.com/channel/UCsItMF6_fP754ihIsSRLk5A/playlists" + "Thelonious Monk": "https://www.youtube.com/@theloniousmonk3870/releases" + "Stan Getz": "https://www.youtube.com/@stangetzofficial/releases" + "Art Blakey": "https://www.youtube.com/channel/UCMki-b0zfAQiMQ0nbsrIuBQ/playlists" -#################################################################################################### -# YOUTUBE - MANY ALBUMS FROM MANY ARTISTS UPLOADED BY A CHANNEL -# See https://www.youtube.com/@heavymetalofeasternbloc -# -# Downloads the entire 'Heavy Metal from the Eastern Bloc' channel. Each video they upload -# is an album from Eastern Europe with chapters representing songs. -eastern_bloc: - # Inherit albums from chapters - preset: "albums_from_chapters" +# Supports downloading a SoundCloud's artists albums + singles. Be sure to not include +# any extension after the SoundCloud artist's name in the URL. +SoundCloud Discography: + = Chill Hop: + "UKNOWY": "https://soundcloud.com/uknowymunich" + = Electronic: + "Italo Brutalo": "https://soundcloud.com/italobrutalo" + "SURVIVE": "https://soundcloud.com/s-u-r-v-i-v-e" + "French79": "https://soundcloud.com/french79music" + "VHS Dreams": "https://soundcloud.com/vhsdreamsofficial" + = Synthwave: + "Lazerdiscs Records": "https://soundcloud.com/lazerdiscsrecords" + "Earmake": "https://soundcloud.com/earmake" + "Poly Poly": "https://soundcloud.com/poly_poly" - # Perform regex on many fields (title, description, chapter title) to extract as much - # metadata as possible - regex: - skip_if_match_fails: False # Error if regex match fails - from: - title: - match: - - "^(.*) - (.*) \\|\\|.*" # Captures artist, album from 'artist - album ||...' - - "^(.*) - (.*) \\[.*" # Captures artist, ablum from 'artist - album [...' - - "^(.*) - (.*)" # Captures artist, ablum from 'artist - album' - capture_group_names: - - "captured_track_artist" - - "captured_track_album" - description: - match: - - "Genre:\\s*(.*)\\s*\n(?:Rec.+|Year):\\s*.*(\\d{4})\\s*\\n" # Captures genre and recorded year - capture_group_names: - - "captured_track_genre" - - "captured_track_year" - chapter_title: - match: - - "^(?:\\d+\\.\\s*|)(.*)" # Captures title from '1. title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{chapter_title}" - - # Explicitly set the URL. - # Override various track properties using the regex variables we extracted. - overrides: - url: "https://www.youtube.com/@heavymetalofeasternbloc" - track_artist: "{captured_track_artist}" - track_album: "{captured_track_album}" - track_title: "{captured_track_title}" - track_year: "{captured_track_year}" - track_genre: "Eastern Bloc {captured_track_genre}" - - -#################################################################################################### -# BANDCAMP - DISCOGRAPHY -# See https://emilyharpist.bandcamp.com/ -# -# Downloads Emily's entire bandcamp discography. yt-dlp represents albums as playlist. -emily_hopkins: - preset: "albums_from_playlists" - regex: - from: - title: - match: - - "^Emily Hopkins - (.*)" # Captures 'title' from 'Emily Hopkins - title' - capture_group_names: - - "captured_track_title" - capture_group_defaults: - - "{title}" - - # Explicitly set the URL, track artist, and genre. - # Override various track properties using the regex variables we extracted. - overrides: - url: "https://emilyharpist.bandcamp.com/" - track_artist: "Emily Hopkins" - track_genre: "Lofi" - track_title: "{captured_track_title}" - - -#################################################################################################### -# SOUNDCLOUD - DISCOGRAPHY -# See https://soundcloud.com/jessebannon -# -# Downloads my acoustic 'album' and various tracks from SoundCloud using the soundcloud -# discography preset. I'm not very good so keep your expectations low :-) -jmbannon: - # Inherit soundcloud_discography preset - preset: "soundcloud_discography" - - # Explicitly set the SoundCloud artist url, track artist, and genre. - overrides: - sc_artist_url: "sc_artist_url" - track_artist: "jmbannon" - track_genre: "Acoustic" +# Supports downloading a Bandcamp artist +Bandcamp: + = Lofi: + "Emily Hopkins": "https://emilyharpist.bandcamp.com/" diff --git a/src/ytdl_sub/cli/entrypoint.py b/src/ytdl_sub/cli/entrypoint.py index 442d04c3..9332df66 100644 --- a/src/ytdl_sub/cli/entrypoint.py +++ b/src/ytdl_sub/cli/entrypoint.py @@ -200,7 +200,7 @@ def main() -> List[Subscription]: config = ConfigFile.from_file_path(DEFAULT_CONFIG_FILE_NAME) else: logger.info("No config specified, using defaults.") - config = ConfigFile(name="default_config", value={}) + config = ConfigFile.default() subscriptions: List[Subscription] = [] diff --git a/src/ytdl_sub/config/config_file.py b/src/ytdl_sub/config/config_file.py index da79e93f..29b136ea 100644 --- a/src/ytdl_sub/config/config_file.py +++ b/src/ytdl_sub/config/config_file.py @@ -84,6 +84,10 @@ class ConfigFile(ConfigValidator): return ConfigFile.from_dict(name=config_path, config_dict=config_dict) + @classmethod + def default(cls) -> "ConfigFile": + return ConfigFile(name="default_config", value={}) + def as_dict(self) -> Dict[str, Any]: """ Returns diff --git a/src/ytdl_sub/prebuilt_presets/music/music.yaml b/src/ytdl_sub/prebuilt_presets/music/music.yaml index d614c4af..274aadb0 100644 --- a/src/ytdl_sub/prebuilt_presets/music/music.yaml +++ b/src/ytdl_sub/prebuilt_presets/music/music.yaml @@ -49,7 +49,7 @@ presets: track_genre: "{subscription_indent_1}" # Directory Overrides - music_directory: "/music/tagged_manual" + music_directory: "/music" artist_dir: "{track_artist_sanitized}" album_dir: "[{track_year}] {track_album_sanitized}" track_file_name: "{track_number_padded} - {track_title_sanitized}.{ext}" diff --git a/tests/conftest.py b/tests/conftest.py index c9d64608..5f310d64 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -186,6 +186,4 @@ def tv_show_subscriptions_path() -> Path: @pytest.fixture() def music_audio_config(working_directory) -> ConfigFile: - return _load_config( - config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory - ) + return ConfigFile.default()