Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions spotdl/providers/audio/bandcamp.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,15 +170,15 @@ class BandCamp(AudioProvider):

def get_results(self, search_term: str, *_args, **_kwargs) -> List[Result]:
"""
Get results from slider.kz
Get results from BandCamp

### Arguments
- search_term: The search term to search for.
- args: Unused.
- kwargs: Unused.

### Returns
- A list of slider.kz results if found, None otherwise.
- A list of BandCamp results if found, None otherwise.
"""

try:
Expand Down
5 changes: 3 additions & 2 deletions spotdl/providers/audio/soundcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:

def get_results(self, search_term: str, *_args, **_kwargs) -> List[Result]:
"""
Get results from slider.kz
Get results from SoundCloud

### Arguments
- search_term: The search term to search for.
- args: Unused.
- kwargs: Unused.

### Returns
- A list of slider.kz results if found, None otherwise.
- A list of SoundCloud results if found, None otherwise.
"""

results = list(islice(self.client.search(search_term), 20))
Expand Down Expand Up @@ -83,6 +83,7 @@ def get_results(self, search_term: str, *_args, **_kwargs) -> List[Result]:
verified=result.user.verified,
duration=result.full_duration,
author=result.user.username,
artists=(result.user.username,),
result_id=str(result.id),
isrc_search=False,
search_query=search_term,
Expand Down
17 changes: 11 additions & 6 deletions spotdl/utils/matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,21 +287,26 @@ def get_best_matches(

def calc_main_artist_match(song: Song, result: Result) -> float:
"""
Check if main artist is present in list of artists
Calculate how well the main artist of the song matches the result.
Falls back to result.author if result.artists is not populated.

### Arguments
- main_artist: main artist to check
- artists: list of artists to check
- song: song to match
- result: result to match

### Returns
- True if main artist is present in list of artists, False otherwise
- artist match percentage (0.0 to 100.0)
"""

main_artist_match = 0.0

# Result has no artists, return 0.0
# Result has no artists, fall back to author
# If no author either, return 0.0
if not result.artists:
return main_artist_match
if not result.author:
return main_artist_match

return ratio(slugify(song.artists[0]), slugify(result.author))

song_artists, result_artists = list(map(slugify, song.artists)), list(
map(slugify, result.artists)
Expand Down
92 changes: 92 additions & 0 deletions tests/test_matching.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from spotdl.providers.audio.base import AudioProviderError
from spotdl.providers.audio.ytmusic import YouTubeMusic
from spotdl.types.result import Result
from spotdl.types.song import Song
from spotdl.utils.matching import calc_main_artist_match
from spotdl.utils.spotify import SpotifyClient
from tests.conftest import new_initialize

Expand Down Expand Up @@ -429,3 +431,93 @@ def test_ytmusic_matching(monkeypatch, query, expected, capsys):

except AudioProviderError:
pytest.skip("YouTube Music search failed")


SONG_DICT = {
"name": "流転の果て",
"artists": ["tokiwa"],
"artist": "tokiwa",
"album_id": "test",
"album_name": "勿忘",
"album_artist": "tokiwa",
"album_type": "album",
"genres": [],
"disc_number": 1,
"disc_count": 1,
"duration": 222,
"year": 2023,
"date": "2023-01-01",
"track_number": 1,
"tracks_count": 1,
"isrc": "",
"song_id": "7yfMsNxODzSIysdZ47JrlG",
"cover_url": "https://example.com/cover.jpg",
"explicit": False,
"publisher": "test",
"url": "https://open.spotify.com/track/7yfMsNxODzSIysdZ47JrlG",
"copyright_text": "",
}


def test_calc_main_artist_match_with_artists():
song = Song.from_dict(SONG_DICT)
result = Result(
source="soundcloud",
url="https://soundcloud.com/tokiwa_anka/pnog8medav1f",
verified=False,
name="流転の果て",
duration=222041,
author="tokiwa",
artists=("tokiwa",),
result_id="941283319",
)

assert calc_main_artist_match(song, result) == 100.0


def test_calc_main_artist_match_falls_back_to_author():
song = Song.from_dict(SONG_DICT)
result = Result(
source="soundcloud",
url="https://soundcloud.com/tokiwa_anka/pnog8medav1f",
verified=False,
name="流転の果て",
duration=222041,
author="tokiwa",
result_id="941283319",
)

assert result.artists is None
assert calc_main_artist_match(song, result) == 100.0


def test_calc_main_artist_match_no_artists_no_author():
song = Song.from_dict(SONG_DICT)
result = Result(
source="soundcloud",
url="https://soundcloud.com/unknown/test",
verified=False,
name="流転の果て",
duration=222041,
author="",
result_id="000",
)

assert result.artists is None
assert calc_main_artist_match(song, result) == 0.0


def test_calc_main_artist_match_author_fuzzy():
song = Song.from_dict({**SONG_DICT, "artists": ["Carly Rae Jepsen"], "artist": "Carly Rae Jepsen"})
result = Result(
source="youtube",
url="https://www.youtube.com/watch?v=abc",
verified=False,
name="I Really Like You",
duration=200,
author="Carly Rae Jepsen - Topic",
result_id="abc",
)

assert result.artists is None
assert calc_main_artist_match(song, result) > 70.0