Skip to content

Commit

Permalink
Merge pull request #20 from dotX12/dev
Browse files Browse the repository at this point in the history
Fixes for #18
  • Loading branch information
dotX12 authored Apr 9, 2022
2 parents 254c0d3 + dc81f2d commit 6b93f34
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 13 deletions.
9 changes: 5 additions & 4 deletions shazamio/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pathlib
import uuid
import time
from pydub import AudioSegment

from typing import Dict, Any, Union

Expand All @@ -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):
Expand Down Expand Up @@ -286,16 +287,16 @@ 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
database.
: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:
Expand Down
4 changes: 2 additions & 2 deletions shazamio/converter.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Union
from io import BytesIO
from pydub import AudioSegment
from shazamio.algorithm import SignatureGenerator
Expand Down Expand Up @@ -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)
Expand Down
41 changes: 41 additions & 0 deletions shazamio/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,51 @@ class FactorySchemas:
name_mapping={
"matches": "matches",
"location": "location",
"retry_ms": "retryms",
"timestamp": "timestamp",
"timezone": "timezone",
"track": "track",
"tag_id": "tagid",
},
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",
}
)
14 changes: 13 additions & 1 deletion shazamio/factory_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
51 changes: 47 additions & 4 deletions shazamio/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -103,8 +140,8 @@ class MatchModel:
id: str
offset: float
channel: str
timeskew: float
frequencyskew: float
time_skew: float
frequency_skew: float


@dataclass
Expand Down Expand Up @@ -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
)

Expand Down Expand Up @@ -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)
Expand Down
10 changes: 8 additions & 2 deletions shazamio/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import pathlib
from typing import Union
from pydub import AudioSegment
from io import BytesIO

import aiofiles
import aiohttp
Expand All @@ -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

0 comments on commit 6b93f34

Please sign in to comment.