diff --git a/shazamio/api.py b/shazamio/api.py index 7cbf781..7c41139 100644 --- a/shazamio/api.py +++ b/shazamio/api.py @@ -1,6 +1,7 @@ import pathlib import uuid import time +from pydub import AudioSegment from typing import Dict, Any, Union @@ -10,7 +11,7 @@ from .enums import GenreMusic from .converter import Converter, Geo from .typehints import CountryCode -from .utils import get_song_bytes +from .utils import get_song class Shazam(Converter, Geo): @@ -286,7 +287,7 @@ async def get_youtube_data(self, link: str) -> Dict[str, Any]: async def recognize_song( self, - data: Union[str, pathlib.Path, bytes, bytearray] + data: Union[str, pathlib.Path, bytes, bytearray, AudioSegment] ) -> Dict[str, Any]: """ Creating a song signature based on a file and searching for this signature in the shazam @@ -294,8 +295,8 @@ async def recognize_song( :param data: Path to song file or bytes :return: Dictionary with information about the found song """ - data_bytes = await get_song_bytes(data=data) - audio = self.normalize_audio_data(data_bytes) + song = await get_song(data=data) + audio = self.normalize_audio_data(song) signature_generator = self.create_signature_generator(audio) signature = signature_generator.get_next_signature() while not signature: diff --git a/shazamio/converter.py b/shazamio/converter.py index 18f2257..9e21366 100644 --- a/shazamio/converter.py +++ b/shazamio/converter.py @@ -1,3 +1,4 @@ +from typing import Union from io import BytesIO from pydub import AudioSegment from shazamio.algorithm import SignatureGenerator @@ -45,8 +46,7 @@ def data_search(timezone: str, uri: str, samplems: int, timestamp: int) -> dict: 'timestamp': timestamp, 'context': {}, 'geolocation': {}} @staticmethod - def normalize_audio_data(song_data: bytes) -> AudioSegment: - audio = AudioSegment.from_file(BytesIO(song_data)) + def normalize_audio_data(audio: AudioSegment) -> AudioSegment: audio = audio.set_sample_width(2) audio = audio.set_frame_rate(16000) audio = audio.set_channels(1) diff --git a/shazamio/factory.py b/shazamio/factory.py index 5e05843..ba6d0cc 100644 --- a/shazamio/factory.py +++ b/shazamio/factory.py @@ -62,6 +62,7 @@ class FactorySchemas: name_mapping={ "matches": "matches", "location": "location", + "retry_ms": "retryms", "timestamp": "timestamp", "timezone": "timezone", "track": "track", @@ -69,3 +70,43 @@ class FactorySchemas: }, skip_internal=True ) + + FACTORY_LYRICS_SECTION = Schema( + name_mapping={ + "type": "type", + "text": "text", + "footer": "footer", + "tab_name": "tabname", + "beacon_data": "beacondata", + }, + ) + + FACTORY_BEACON_DATA_LYRICS_SECTION = Schema( + name_mapping={ + "lyrics_id": "lyricsid", + "provider_name": "providername", + "common_track_id": "commontrackid", + } + ) + + FACTORY_ARTIST_SECTION = Schema( + name_mapping={ + "type": "type", + "id": "id", + "name": "name", + "verified": "verified", + "actions": "actions", + "tab_name": "tabname", + "top_tracks": "toptracks", + } + ) + + FACTORY_MATCH_MODEL = Schema( + name_mapping={ + "id": "id", + "offset": "offset", + "channel": "channel", + "time_skew": "timeskew", + "frequency_skew": "frequencyskew", + } + ) diff --git a/shazamio/factory_misc.py b/shazamio/factory_misc.py index 7c60645..5bf31e3 100644 --- a/shazamio/factory_misc.py +++ b/shazamio/factory_misc.py @@ -2,7 +2,15 @@ from shazamio.factory import FactorySchemas from shazamio.models import ArtistInfo -from shazamio.models import SongSection, VideoSection, RelatedSection +from shazamio.models import ( + SongSection, + VideoSection, + RelatedSection, + LyricsSection, + BeaconDataLyricsSection, + ArtistSection, + MatchModel, +) from shazamio.models import TrackInfo from shazamio.models import YoutubeData from shazamio.models import ResponseTrack @@ -11,6 +19,10 @@ TrackInfo: FactorySchemas.FACTORY_TRACK_SCHEMA, SongSection: FactorySchemas.FACTORY_SONG_SECTION_SCHEMA, VideoSection: FactorySchemas.FACTORY_VIDEO_SECTION_SCHEMA, + LyricsSection: FactorySchemas.FACTORY_LYRICS_SECTION, + BeaconDataLyricsSection: FactorySchemas.FACTORY_BEACON_DATA_LYRICS_SECTION, + ArtistSection: FactorySchemas.FACTORY_ARTIST_SECTION, + MatchModel: FactorySchemas.FACTORY_MATCH_MODEL, RelatedSection: FactorySchemas.FACTORY_RELATED_SECTION_SCHEMA, YoutubeData: FactorySchemas.FACTORY_YOUTUBE_TRACK_SCHEMA, ResponseTrack: FactorySchemas.FACTORY_RESPONSE_TRACK_SCHEMA, diff --git a/shazamio/models.py b/shazamio/models.py index 8cfa61e..570449b 100644 --- a/shazamio/models.py +++ b/shazamio/models.py @@ -72,6 +72,43 @@ class SongSection: metadata: List[SongMetadata] +@dataclass +class BaseIdTypeModel: + type: str + id: str + + +@dataclass +class TopTracksModel: + url: str + + +@dataclass +class ArtistSection: + type: str + id: str + name: str + verified: bool + actions: List[BaseIdTypeModel] + tab_name: str + top_tracks: TopTracksModel + + +class BeaconDataLyricsSection: + lyrics_id: str + provider_name: str + common_track_id: str + + +@dataclass +class LyricsSection: + type: str + text: List[str] + footer: str + tab_name: str + beacon_data: Optional[BeaconDataLyricsSection] + + @dataclass class VideoSection: type: str @@ -103,8 +140,8 @@ class MatchModel: id: str offset: float channel: str - timeskew: float - frequencyskew: float + time_skew: float + frequency_skew: float @dataclass @@ -143,7 +180,13 @@ class TrackInfo(Factory): spotify_url: Optional[str] = field(default=None) spotify_uri: Optional[str] = field(default=None) youtube_link: Optional[str] = None - _sections: Optional[List[Union[SongSection, VideoSection, RelatedSection]]] = field( + _sections: Optional[List[Union[ + SongSection, + VideoSection, + RelatedSection, + ArtistSection, + LyricsSection, + ]]] = field( default_factory=list ) @@ -172,7 +215,7 @@ def __youtube_link(self): @dataclass class ResponseTrack: tag_id: Optional[UUID] - retryms: Optional[int] = field(default=None) + retry_ms: Optional[int] = field(default=None) location: Optional[LocationModel] = field(default=None) matches: List[MatchModel] = field(default_factory=list) timestamp: Optional[int] = field(default=None) diff --git a/shazamio/utils.py b/shazamio/utils.py index be702ce..1ff22a2 100644 --- a/shazamio/utils.py +++ b/shazamio/utils.py @@ -1,5 +1,7 @@ import pathlib from typing import Union +from pydub import AudioSegment +from io import BytesIO import aiofiles import aiohttp @@ -23,11 +25,15 @@ async def get_file_bytes(file: FileT) -> bytes: return await f.read() -async def get_song_bytes(data: SongT) -> bytes: +async def get_song(data: SongT) -> bytes: if isinstance(data, (str, pathlib.Path)): - return await get_file_bytes(file=data) + song_bytes = await get_file_bytes(file=data) + return AudioSegment.from_file(BytesIO(song_bytes)) if isinstance(data, (bytes, bytearray)): + return AudioSegment.from_file(BytesIO(data)) + + if isinstance(data, AudioSegment): return data