diff --git a/api/funkwhale_api/radios/radios.py b/api/funkwhale_api/radios/radios.py index 4f23fb281..ef1931d5f 100644 --- a/api/funkwhale_api/radios/radios.py +++ b/api/funkwhale_api/radios/radios.py @@ -1,3 +1,4 @@ +import logging import random from django.core.exceptions import ValidationError @@ -11,9 +12,11 @@ from funkwhale_api.moderation import filters as moderation_filters from funkwhale_api.music.models import Artist, Library, Track, Upload from funkwhale_api.tags.models import Tag -from . import filters, models +from . import filters, models, utils from .registries import registry +logger = logging.getLogger(__name__) + class SimpleRadio(object): related_object_field = None @@ -201,7 +204,7 @@ class NextNotFound(Exception): pass -@registry.register(name="similar") +@registry.register(name="similar_history") class SimilarRadio(RelatedObjectRadio): model = Track @@ -254,6 +257,27 @@ class SimilarRadio(RelatedObjectRadio): return random.choice([c[0] for c in next_candidates]) +@registry.register(name="similar_mbid") +class SimilarAcousticRadio(RelatedObjectRadio): + model = Track + + def get_regex(self): + related_mbid = str(self.session.related_object.mbid) + if not related_mbid: + logger.info(f"No mbid found for the related object.") + pass + mbids_regex = str() + mbids = utils.get_similar_tracks_mbids_from_mbid(related_mbid, "rosamerica") + for mbid in mbids: + mbids_regex = str(mbids_regex) + str(mbid + "|") + return mbids_regex + + def filter_queryset(self, queryset): + queryset = super().filter_queryset(queryset) + mbids_regex = self.get_regex() + return queryset.filter(mbid__regex=r'({mbids_regex})'.format(mbids_regex=mbids_regex)) + + @registry.register(name="artist") class ArtistRadio(RelatedObjectRadio): model = Artist diff --git a/api/funkwhale_api/radios/utils.py b/api/funkwhale_api/radios/utils.py new file mode 100644 index 000000000..1190b78b5 --- /dev/null +++ b/api/funkwhale_api/radios/utils.py @@ -0,0 +1,35 @@ +import json +import logging + +import requests + +logger = logging.getLogger(__name__) + +VALID_METRICS = ['mfccs', 'mfccsw', 'gfccs', 'gfccsw', 'key', 'bpm', 'onsetrate', 'moods', + 'instruments', 'dortmund', 'rosamerica', 'tzanetakis'] + + +class EndpointError(Exception): + pass + + +def get_similar_tracks_mbids_from_mbid(mbid, annoy_similarity): + + if annoy_similarity not in VALID_METRICS: + raise AttributeError("Metric %s is not valid. Must be one of : " + print(VALID_METRICS)) + + headers = {'Content-Type': 'application/json'} + endpoint = "acousticbrainz.org/api/v1/similarity" + similar_tracks_mbids = [] + similar_tracks = requests.get( + 'https://{endpoint}/{annoy_similarity}/?recording_ids={mbid}&remove_dups&n_neighbours=1000' + .format(endpoint=endpoint, annoy_similarity=annoy_similarity, mbid=mbid), headers=headers + ) + if similar_tracks.status_code != 200: + logger.warning("Error while querying {endpoint!r} : {similar_tracks.content!r}") + raise EndpointError + + j = json.loads(similar_tracks.content) + for tracks in j['{mbid}'.format(mbid=mbid)]['0']: + similar_tracks_mbids.append(tracks['recording_mbid']) + return similar_tracks_mbids diff --git a/front/src/components/audio/PlayButton.vue b/front/src/components/audio/PlayButton.vue index dd0e65132..564ac3d7f 100644 --- a/front/src/components/audio/PlayButton.vue +++ b/front/src/components/audio/PlayButton.vue @@ -25,7 +25,7 @@ -