Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sonicallySimilar method to Audio class #1288

Merged
merged 9 commits into from
Nov 13, 2023
31 changes: 31 additions & 0 deletions plexapi/audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
from pathlib import Path
from urllib.parse import quote_plus

from typing import TypeVar

from plexapi import media, utils
from plexapi.base import Playable, PlexPartialObject, PlexHistory, PlexSession
from plexapi.exceptions import BadRequest
Expand All @@ -14,6 +16,9 @@
from plexapi.playlist import Playlist


Self = TypeVar("Self", bound="Audio")
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved


class Audio(PlexPartialObject, PlayedUnplayedMixin):
""" Base class for all audio objects including :class:`~plexapi.audio.Artist`,
:class:`~plexapi.audio.Album`, and :class:`~plexapi.audio.Track`.
Expand All @@ -34,6 +39,7 @@ class Audio(PlexPartialObject, PlayedUnplayedMixin):
listType (str): Hardcoded as 'audio' (useful for search filters).
moods (List<:class:`~plexapi.media.Mood`>): List of mood objects.
musicAnalysisVersion (int): The Plex music analysis version for the item.
distance (float): Sonic Distance of the item from the seed item.
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
ratingKey (int): Unique key identifying the item.
summary (str): Summary of the artist, album, or track.
thumb (str): URL to thumbnail image (/library/metadata/<ratingKey>/thumb/<thumbid>).
Expand Down Expand Up @@ -65,6 +71,7 @@ def _loadData(self, data):
self.listType = 'audio'
self.moods = self.findItems(data, media.Mood)
self.musicAnalysisVersion = utils.cast(int, data.attrib.get('musicAnalysisVersion'))
self.distance = utils.cast(float, data.attrib.get('distance'))
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
self.ratingKey = utils.cast(int, data.attrib.get('ratingKey'))
self.summary = data.attrib.get('summary')
self.thumb = data.attrib.get('thumb')
Expand Down Expand Up @@ -125,6 +132,30 @@ def sync(self, bitrate, client=None, clientId=None, limit=None, title=None):

return myplex.sync(sync_item, client=client, clientId=clientId)

def sonicallySimilar(
self: Self,
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
limit: int = 30,
maxDistance: float = 0.25,
**kwargs,
) -> "list[Self]":
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
""" Find sonically similar audio items.
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved

Parameters:
limit (int): maximum count of items to return, unlimited if `None`.
maxDistance (float): maximum distance between tracks, 0.0 - 1.0.
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
**kwargs: Additional options passed into :func:`~plexapi.base.PlexObject.fetchItems`.

Returns:
List[:class:`~plexapi.audio.Audio`]: list of sonically similar audio items.
"""

key = f"/library/metadata/{self.ratingKey}/nearest?limit={limit}&maxDistance={maxDistance}"
Dr-Blank marked this conversation as resolved.
Show resolved Hide resolved
return self.fetchItems(
key,
cls=self.__class__,
**kwargs,
)


@utils.registerPlexObject
class Artist(
Expand Down