diff --git a/examples/music_audio_from_videos.yaml b/examples/music_audio_config.yaml similarity index 78% rename from examples/music_audio_from_videos.yaml rename to examples/music_audio_config.yaml index 72daacac..70bc40fb 100644 --- a/examples/music_audio_from_videos.yaml +++ b/examples/music_audio_config.yaml @@ -153,4 +153,43 @@ presets: track_album: "{title}" # Video's title is the album title track_number: "{chapter_index}" track_number_padded: "{chapter_index_padded}" - track_total: "{chapter_count}" \ No newline at end of file + 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: + download_strategy: "multi_url" + urls: + # 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_from_videos_subscriptions.yaml b/examples/music_audio_subscriptions.yaml similarity index 96% rename from examples/music_audio_from_videos_subscriptions.yaml rename to examples/music_audio_subscriptions.yaml index 797090ba..7786664a 100644 --- a/examples/music_audio_from_videos_subscriptions.yaml +++ b/examples/music_audio_subscriptions.yaml @@ -17,6 +17,7 @@ # #################################################################################################### # 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. @@ -44,9 +45,9 @@ game_chops: track_title: "{captured_track_title}" - #################################################################################################### # BANDCAMP - DISCOGRAPHY +# See https://emilyharpist.bandcamp.com/ # # Downloads the GameChops Albums' playlist. Each video in the playlist is an album with # chapters representing songs. @@ -71,9 +72,9 @@ emily_hopkins: track_title: "{captured_track_title}" - #################################################################################################### # 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. diff --git a/examples/soundcloud_discography_config.yaml b/examples/soundcloud_discography_config.yaml deleted file mode 100644 index cf7c33da..00000000 --- a/examples/soundcloud_discography_config.yaml +++ /dev/null @@ -1,88 +0,0 @@ -# This example shows how to download and format a Soundcloud artist's -# discography with tags and album art. We will configure this to make -# the output directory formatted as: -# -# /path/to/music -# /The Be Sharps -# /[2020] My first upload -# 01 - My first upload.mp3 -# folder.jpg -# /[2021] My first album -# 01 - Track one.mp3 -# 02 - Track two.mp3 -# folder.jpg -# /Another artist -# ... -# -configuration: - working_directory: '.ytdl-sub-downloads' - -presets: - soundcloud_discography: - # Download using the multi_url strategy - download: - download_strategy: "multi_url" - urls: - # The first URL will be all the artist's tracks. - # Treat these as singles - an album with a single track - - url: "{artist_url}/tracks" - variables: - track_number: "1" - track_number_padded: "01" - track_count: "1" - album: "{title}" - album_sanitized: "{title_sanitized}" - album_year: "{upload_year}" - # Set the second URL to the artist's albums. If a track belongs 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: "{artist_url}/albums" - variables: - track_number: "{playlist_index}" - track_number_padded: "{playlist_index_padded}" - track_count: "{playlist_count}" - album: "{playlist_title}" - album_sanitized: "{playlist_title_sanitized}" - album_year: "{playlist_max_upload_year}" - - # For advanced YTDL users only; set any YTDL parameter here. - # Let us set the format to download the best mp3. - ytdl_options: - format: 'bestaudio[ext=mp3]' - - # For each song downloaded, set the file and thumbnail name here. - # The output directory stores all artists in a shared {music_directory}. - # We store the audio file in its respective {album_directory_name} folder - # with the track number and title. The (thumbnail) album art is stored - # in the album folder. - # - # Set maintain_download_archive=True. This will tell YTDL not to - # re-download them on a successive invocation. - output_options: - output_directory: "{music_directory}" - file_name: "{album_path}/{track_file_name}.{ext}" - thumbnail_name: "{album_path}/folder.{thumbnail_ext}" - maintain_download_archive: True - - # For each song downloaded, populate the audio file with music tags. - # Tagging should work with most audio file formats. See - # https://ytdl-sub.readthedocs.io/en/latest/config.html#music-tags - # for more details. - music_tags: - tags: - artist: "{artist}" - albumartist: "{artist}" - title: "{title}" - album: "{album}" - track: "{track_number}" - year: "{album_year}" - genre: "Unset" - - # Overrides is a section where we can define our own variables, and use them in - # any other section. We define our music directory and album directory names here, - # which gets reused above for the audio file name and album art path. - overrides: - album_directory_name: "[{album_year}] {album_sanitized}" - track_file_name: "{track_number_padded} - {title_sanitized}" - album_path: "{artist_sanitized}/{album_directory_name}" - music_directory: "/path/to/music" \ No newline at end of file diff --git a/tests/e2e/bandcamp/test_bandcamp.py b/tests/e2e/bandcamp/test_bandcamp.py index 9235f7be..32f96511 100644 --- a/tests/e2e/bandcamp/test_bandcamp.py +++ b/tests/e2e/bandcamp/test_bandcamp.py @@ -38,14 +38,14 @@ class TestBandcamp: def test_download_artist_url( self, subscription_dict, - youtube_audio_config, + music_audio_config, output_directory, dry_run, ): discography_subscription = Subscription.from_dict( preset_dict=subscription_dict, preset_name="jb", - config=youtube_audio_config, + config=music_audio_config, ) transaction_log = discography_subscription.download(dry_run=dry_run) assert_transaction_log_matches( diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index aadbb1d8..803d38a1 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -88,9 +88,9 @@ def soundcloud_discography_config(working_directory) -> ConfigFile: @pytest.fixture() -def youtube_audio_config(working_directory) -> ConfigFile: +def music_audio_config(working_directory) -> ConfigFile: return _load_config( - config_path="examples/music_audio_from_videos.yaml", working_directory=working_directory + config_path="examples/music_audio_config.yaml", working_directory=working_directory ) diff --git a/tests/e2e/plugins/test_audio_extract.py b/tests/e2e/plugins/test_audio_extract.py index 3a87828f..7e7a4758 100644 --- a/tests/e2e/plugins/test_audio_extract.py +++ b/tests/e2e/plugins/test_audio_extract.py @@ -44,13 +44,13 @@ class TestAudioExtract: @pytest.mark.parametrize("dry_run", [True, False]) def test_audio_extract_single_song( self, - youtube_audio_config, + music_audio_config, single_song_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="single_song_test", preset_dict=single_song_preset_dict, ) @@ -70,13 +70,13 @@ class TestAudioExtract: @pytest.mark.parametrize("dry_run", [True, False]) def test_audio_extract_multiple_songs( self, - youtube_audio_config, + music_audio_config, multiple_songs_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="multiple_songs_test", preset_dict=multiple_songs_preset_dict, ) diff --git a/tests/e2e/plugins/test_music_tags.py b/tests/e2e/plugins/test_music_tags.py index 2cec1b9b..c6cecf21 100644 --- a/tests/e2e/plugins/test_music_tags.py +++ b/tests/e2e/plugins/test_music_tags.py @@ -29,12 +29,12 @@ def single_song_video_dict(output_directory): class TestMusicTags: def test_music_tags_errors_on_video( self, - youtube_audio_config, + music_audio_config, single_song_video_dict, output_directory, ): subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="single_song_test", preset_dict=single_song_video_dict, ) diff --git a/tests/e2e/plugins/test_split_by_chapters.py b/tests/e2e/plugins/test_split_by_chapters.py index 1320bc3a..60e77a36 100644 --- a/tests/e2e/plugins/test_split_by_chapters.py +++ b/tests/e2e/plugins/test_split_by_chapters.py @@ -66,13 +66,13 @@ class TestSplitByChapters: @pytest.mark.parametrize("dry_run", [True, False]) def test_video_with_chapters( self, - youtube_audio_config, + music_audio_config, yt_album_as_chapters_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="split_by_chapters_video", preset_dict=yt_album_as_chapters_preset_dict, ) @@ -96,13 +96,13 @@ class TestSplitByChapters: @pytest.mark.parametrize("dry_run", [True, False]) def test_video_with_chapters_and_regex( self, - youtube_audio_config, + music_audio_config, yt_album_as_chapters_with_regex_preset_dict, output_directory, dry_run, ): subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="split_by_chapters_with_regex_video", preset_dict=yt_album_as_chapters_with_regex_preset_dict, ) @@ -123,7 +123,7 @@ class TestSplitByChapters: @pytest.mark.parametrize("when_no_chapters", ["pass", "drop", "error"]) def test_video_with_no_chapters_and_regex( self, - youtube_audio_config, + music_audio_config, yt_album_as_chapters_with_regex_preset_dict, output_directory, dry_run, @@ -138,7 +138,7 @@ class TestSplitByChapters: ) subscription = Subscription.from_dict( - config=youtube_audio_config, + config=music_audio_config, preset_name="split_by_chapters_with_regex_video", preset_dict=yt_album_as_chapters_with_regex_preset_dict, ) diff --git a/tests/e2e/soundcloud/test_soundcloud_discography.py b/tests/e2e/soundcloud/test_soundcloud_discography.py index 4115b7f3..f435245e 100644 --- a/tests/e2e/soundcloud/test_soundcloud_discography.py +++ b/tests/e2e/soundcloud/test_soundcloud_discography.py @@ -14,8 +14,8 @@ def subscription_dict(output_directory): "format": "worst[ext=mp3]", }, "overrides": { - "artist": "j_b", - "artist_url": "https://soundcloud.com/jessebannon", + "track_artist": "j_b", + "sc_artist_url": "https://soundcloud.com/jessebannon", "music_directory": output_directory, }, } @@ -31,14 +31,14 @@ class TestSoundcloudDiscography: def test_discography_download( self, subscription_dict, - soundcloud_discography_config, + music_audio_config, output_directory, dry_run, ): discography_subscription = Subscription.from_dict( preset_dict=subscription_dict, preset_name="jb", - config=soundcloud_discography_config, + config=music_audio_config, ) transaction_log = discography_subscription.download(dry_run=dry_run) assert_transaction_log_matches( diff --git a/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt b/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt index 3e51150d..86015ee3 100644 --- a/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt +++ b/tests/resources/transaction_log_summaries/soundcloud/test_soundcloud_discography.txt @@ -7,10 +7,13 @@ Files created: Music Tags: album: Baby Santana's Dorian Groove albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: Baby Santana's Dorian Groove track: 1 + tracktotal: 1 year: 2021 folder.jpg {output_directory}/j_b/[2021] Purple Clouds @@ -18,10 +21,13 @@ Files created: Music Tags: album: Purple Clouds albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: Purple Clouds track: 1 + tracktotal: 1 year: 2021 folder.jpg {output_directory}/j_b/[2022] Acoustic Treats @@ -29,99 +35,132 @@ Files created: Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20160426 184214 track: 1 + tracktotal: 11 year: 2022 02 - 20160502 123150.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20160502 123150 track: 2 + tracktotal: 11 year: 2022 03 - 20160504 143832.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20160504 143832 track: 3 + tracktotal: 11 year: 2022 04 - 20160601 221234.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20160601 221234 track: 4 + tracktotal: 11 year: 2022 05 - 20160601 222440.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20160601 222440 track: 5 + tracktotal: 11 year: 2022 06 - 20170604 190236.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20170604 190236 track: 6 + tracktotal: 11 year: 2022 07 - 20170612 193646.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20170612 193646 track: 7 + tracktotal: 11 year: 2022 08 - 20170628 215206.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: 20170628 215206 track: 8 + tracktotal: 11 year: 2022 09 - Finding Home.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: Finding Home track: 9 + tracktotal: 11 year: 2022 10 - Shallow Water WIP.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: Shallow Water WIP track: 10 + tracktotal: 11 year: 2022 11 - Untold History.mp3 Music Tags: album: Acoustic Treats albumartist: j_b + albumartists: j_b artist: j_b + artists: j_b genre: Unset title: Untold History track: 11 + tracktotal: 11 year: 2022 folder.jpg \ No newline at end of file