Skip to content
shazamioPublic

About

🎡 Is a free asynchronous library from reverse engineered Shazam API written in Python 3.10+ with asyncio and aiohttp.

Topics

Resources

Code of conduct

Contributing

Stars

974 stars

Watchers

10 watching

Forks

Latest commit

Β 

History

434 Commits

Folders and files

Repository files navigation

https://scrutinizer-ci.com/g/dotX12/ShazamIO/ https://scrutinizer-ci.com/g/dotX12/ShazamIO/ https://scrutinizer-ci.com/g/dotX12/ShazamIO/ https://badge.fury.io/py/shazamio https://pepy.tech/project/shazamio https://pepy.tech/project/shazamio https://github.com/dotX12/ShazamIO/blob/master/LICENSE.txt

🎡 Is a FREE asynchronous library from reverse engineered Shazam API written in Python 3.10+ with asyncio and aiohttp. Recognizes a song from a file or from bytes, reads a track, and returns every chart Shazam publishes.


πŸ’Ώ Installation

πŸ’² pip install shazamio

πŸ’» Example

πŸ”ŽπŸŽ΅ Recognize track

Recognize a track from a file, a pathlib.Path, or the bytes of one. The sample below ships with the repository, in examples/data/. The signature covers 12 s of the audio, the window Shazam clients send; segment_duration_seconds still takes another one and warns, and from 15 s up Shazam finds nothing at all

import asyncio
from shazamio import Serialize, Shazam


async def main():
    async with Shazam() as shazam:
        out = await shazam.recognize("Gloria.ogg")

        print(out)  # dict
        print(Serialize.full_track(out).track.title)  # I Will Survive


asyncio.run(main())
πŸŽ΅πŸ“„ About track

Get track information
https://www.shazam.com/track/552406075/ale-jazz

import asyncio
from shazamio import Serialize, Shazam


async def main():
    async with Shazam() as shazam:
        about_track = await shazam.track_about(track_id=552406075)

        print(about_track)  # dict
        print(Serialize.track(data=about_track))  # pydantic model


asyncio.run(main())
πŸŽπŸ”‘ Apple Music ids to Shazam track keys

Resolve Apple Music track ids to the Shazam track keys track_about takes, in one request. A call with several ids keys every entry by the id Shazam stores, which can be one you never sent, so read the values instead of indexing by what you asked for. A call with a single id keys it by that id. Either way an id Shazam has no track for is absent, so the map can be shorter than the list you passed.

import asyncio
from shazamio import Shazam


async def main():
    async with Shazam() as shazam:
        keys = await shazam.track_keys_from_apple_ids([1125281672, 1440650711])

        print(keys)  # {'1125281672': '325127876', '6781023657': '56670613'}


asyncio.run(main())
πŸ”ŽπŸŽΆ Search tracks by text, through Apple's index

Shazam no longer answers text search, so this searches Apple's iTunes index and fetches the Shazam track of every song found. Relevance and order are Apple's. Songs Shazam has no track for are left out and versions sharing one Shazam track come back once, so you can get fewer tracks than limit. Each song costs two requests, which is why limit defaults to 5.

import asyncio
from shazamio import Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.search_tracks_via_itunes("daft punk one more time")

        print([track["title"] for track in tracks])
        # ['One More Time', 'One More Time (12 Mix)', "One More Time (Romanthony's Unplugged)"]


asyncio.run(main())
πŸ”πŸŽΆπŸŒ Top tracks in world

The 200 most shazamed tracks worldwide
https://www.shazam.com/charts/top-200/world

import asyncio
from shazamio import Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.top_world_tracks(limit=10)

        for track in tracks:
            print(f"{track.rank}. {track.artist} - {track.title}")


asyncio.run(main())
πŸ”πŸŽΆπŸ³οΈ Top tracks in country

The 200 most shazamed tracks in a country
https://www.shazam.com/charts/top-200/netherlands

import asyncio
from shazamio import Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.top_country_tracks(
            country_code="NL",
            limit=5,
        )

        for track in tracks:
            print(f"{track.rank}. {track.artist} - {track.title}")


asyncio.run(main())
πŸ”πŸŽΆπŸ™οΈ Top tracks in city

The 50 most shazamed tracks in a city. The city name is the one services/charts/locations publishes
https://www.shazam.com/charts/top-50/russia/moscow

import asyncio
from shazamio import Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.top_city_tracks(
            country_code="RU",
            city_name="Moscow",
            limit=10,
        )

        for track in tracks:
            print(f"{track.rank}. {track.artist} - {track.title}")


asyncio.run(main())
πŸ”πŸŽΆπŸŒπŸŽΈ Top tracks in world by genre

The most shazamed tracks worldwide in one genre
https://www.shazam.com/charts/genre/world/rock

import asyncio
from shazamio import GenreMusic, Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.top_world_genre_tracks(
            genre=GenreMusic.ROCK,
            limit=10,
        )

        for track in tracks:
            print(f"{track.rank}. {track.artist} - {track.title}")


asyncio.run(main())
πŸ”πŸŽΆπŸ³οΈπŸŽΈ Top tracks in country by genre

The most shazamed tracks in a country in one genre. Shazam offers only a handful of genres per country, and asking for one it does not offer answers 404, which surfaces as aiohttp.ClientResponseError
https://www.shazam.com/charts/genre/spain/hip-hop-rap

import asyncio
from shazamio import GenreMusic, Shazam


async def main():
    async with Shazam() as shazam:
        tracks = await shazam.top_country_genre_tracks(
            country_code="ES",
            genre=GenreMusic.HIP_HOP_RAP,
            limit=4,
        )

        for track in tracks:
            print(f"{track.rank}. {track.artist} - {track.title}")


asyncio.run(main())

πŸ”Œ Closing what you open

A Shazam opens one connection pool on its first request and reuses it for every later one, so ten calls no longer cost ten connections. The pool lives until you close it, which async with does for you:

async with Shazam() as shazam:
    ...

Without a close the pool stays open and aiohttp reports it when the object is collected: Unclosed client session. await shazam.close() does the same job where a block does not fit, and a request after either one raises RuntimeError: Session is closed.

A pool belongs to the event loop it was opened on. A Shazam kept across several asyncio.run calls opens a new pool on each new loop and abandons the old one, which aiohttp reports the same way. A closed Shazam stays closed in every loop. Prefer one asyncio.run around all the calls.

An HTTPClient you build yourself is yours to close: Shazam closes only the client it builds for itself. examples/recognize_song.py shows both blocks.

πŸ“Š What the chart methods return

Shazam publishes its charts as CSV with three columns, so a chart entry is a ChartTrack carrying a rank, an artist and a title, and nothing else. A chart has no ids, no artwork and no provider links, so a chart entry cannot be passed to Serialize. Nothing in the library resolves a chart row to a track id either: Shazam retired the search endpoints that used to do it.

limit defaults to the whole chart, and offset skips entries from the top: both are applied to the chart the service returns, which is always the full one.

πŸ”§ What data serialization gives you

Serialize.full_track turns the output of recognize into a ResponseTrack, and Serialize.track turns the output of track_about into a TrackInfo. Both carry the title, the artist, the artwork and the provider links, so you no longer have to pick the fields out of the raw dictionary by hand.

Open photo: What song information looks like (Dict)
Open photo: what song information looks like (Custom serializer)

About

🎡 Is a free asynchronous library from reverse engineered Shazam API written in Python 3.10+ with asyncio and aiohttp.

Topics

Resources

Code of conduct

Contributing

Stars

974 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages