Metadata-Version: 2.4
Name: shazamlite
Version: 0.1.0
Summary: Lightweight, reliable Shazam recognition for Python with a pure-Python fingerprinting engine.
License-Expression: MIT
Project-URL: Homepage, https://dytuk.media/shazamlite
Project-URL: Repository, https://github.com/danielytuk/shazamlite
Project-URL: Issues, https://github.com/danielytuk/shazamlite/issues
Project-URL: Documentation, https://github.com/danielytuk/shazamlite#readme
Keywords: shazam,audio,fingerprinting,recognition,music,itunes
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Operating System :: OS Independent
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.21
Provides-Extra: curl-cffi
Requires-Dist: curl_cffi>=0.6.0; extra == "curl-cffi"
Provides-Extra: soundfile
Requires-Dist: soundfile>=0.12; extra == "soundfile"
Provides-Extra: miniaudio
Requires-Dist: miniaudio>=1.57; extra == "miniaudio"
Provides-Extra: tzlocal
Requires-Dist: tzlocal>=5.0; extra == "tzlocal"
Provides-Extra: mic
Requires-Dist: sounddevice>=0.4.6; extra == "mic"
Provides-Extra: pydub
Requires-Dist: pydub>=0.25; extra == "pydub"
Provides-Extra: all
Requires-Dist: curl_cffi>=0.6.0; extra == "all"
Requires-Dist: soundfile>=0.12; extra == "all"
Requires-Dist: miniaudio>=1.57; extra == "all"
Requires-Dist: tzlocal>=5.0; extra == "all"
Requires-Dist: sounddevice>=0.4.6; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ShazamIO>=0.8; extra == "dev"
Dynamic: license-file

# shazamlite

[![CI](https://github.com/danielytuk/shazamlite/actions/workflows/ci.yml/badge.svg)](https://github.com/danielytuk/shazamlite/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)

Identify any song from audio, with a pure-Python fingerprinting engine and live
Shazam recognition — no API keys required.

`shazamlite` implements Shazam's legacy audio-signature algorithm in pure Python
+ numpy (byte-identical to ShazamIO's `SignatureGenerator`), sends the signature
to Shazam's live `discovery/v5` endpoint, and enriches results with iTunes
metadata (artwork, album, previews).

> **Transparency:** this project is a 50/50 collaboration between human
> creativity and AI implementation. The initial concept, requirements, and
> rough functionality were created by a human developer, then refined and
> polished by AI to ensure smooth functionality, proper error handling, and
> production-ready code quality.

## Features

- **Recognition** — match audio against Shazam's live `discovery/v5` endpoint.
  Long files are scanned across their loudest windows, so quiet intros or
  trailing silence never block a match.
- **Signature engine** — `shazamlite.signature` is a dependency-free reimpl of
  the legacy Shazam algorithm; output is byte-identical to ShazamIO
  (`data:audio/vnd.shazam.sig`).
- **Metadata** — search (iTunes Search), world + genre charts (official CSVs),
  related tracks, artist info and top songs, all enriched with 600×600 artwork.
- **Optional extras** — Chrome TLS impersonation (`curl_cffi`), broad audio
  decoding (`soundfile`/`miniaudio`), live-mic capture (`sounddevice`),
  accurate timezone detection (`tzlocal`), `pydub` support.
- **Sync + async facades**, JSON-serializable dataclasses, rich errors with
  status code + body + URL.

Only `numpy` is required. Everything else is optional.

## Install

```bash
pip install shazamlite                 # + numpy
pip install "shazamlite[all]"          # + curl_cffi, soundfile, miniaudio, tzlocal, sounddevice
```

| Extra         | Provides                                         |
| ------------- | ------------------------------------------------ |
| `curl-cffi`   | Chrome TLS impersonation (JA3/JA4/HTTP2)         |
| `soundfile`   | Decode mp3 / flac / ogg / m4a files              |
| `miniaudio`   | Alternative universal decoder                    |
| `tzlocal`     | Accurate local timezone detection                |
| `mic`         | Live microphone capture via `sounddevice`        |
| `pydub`       | Accept `pydub.AudioSegment` objects directly     |
| `dev`         | pytest + ShazamIO (byte-parity test)             |

## Quick start

```python
import asyncio
from shazamlite import Shazam, ShazamAsync

shazam = Shazam(country="US")

track = shazam.recognize("song.mp3")     # path, WAV bytes, numpy array, or pydub segment
print(track.title, "-", track.artist)    # "Won't Bite (feat. Smino) - Doja Cat"
print(track.coverart)                    # 600x600 artwork URL
print(track.to_dict())                   # JSON-serializable dict

# Async
async def main():
    return await ShazamAsync().recognize("song.flac")

asyncio.run(main())
```

`recognize()` accepts a file path, raw WAV bytes, a numpy float array
(pass `sample_rate=` for anything other than 16 kHz), or a `pydub.AudioSegment`.
For recordings of speech or noise the server simply answers "no match".

## CLI

```bash
shazamlite recognize song.mp3
shazamlite search "olivia rodrigo" --limit 5
shazamlite charts --world
shazamlite charts --country FR
shazamlite charts --country US --city "New York"
shazamlite charts --genre pop
shazamlite related 502331060
shazamlite artist 830588310 --top-songs
```

All output is JSON. Global flags: `--country`, `--language`, `--timezone`,
`--endpoint`, `--no-enrich`, `--json`.

## Metadata

```python
shazam.search("queen bohemian", limit=5)
shazam.top_world_charts(limit=10)
shazam.top_genre_charts("pop")          # genre/world charts
shazam.top_country_charts("FR")         # note: country CSVs are 404 server-side (2026-08)
shazam.top_city_charts("US", "New York")# note: city CSVs are 404 server-side (2026-08)
shazam.related_tracks("502331060")
shazam.artist_about("830588310")        # -> {"artist_id", "name"}
shazam.artist_top_songs("830588310")
```

## Errors

All errors derive from `ShazamError`.

| Error                  | Meaning                                               |
| ---------------------- | ----------------------------------------------------- |
| `NoMatch`              | Server answered, but nothing matched                 |
| `BadData`              | Not enough audio for a signature, or undecodable input |
| `FailedDecodeJson`     | Response was not valid JSON                          |
| `HTTPStatusError`      | Non-2xx (or persistent 429/5xx) — carries code, body, URL |
| `MaxRetriesExceeded`   | Transport failure after all retry attempts            |

429/5xx responses are retried with exponential backoff + jitter (default 3 attempts).

## Development

```bash
pip install ".[dev]"
pytest                       # full suite (59 tests)
pytest tests/test_parity.py  # byte-parity vs ShazamIO
```

## License

MIT — see [LICENSE](LICENSE).

---

© 2026 Daniel Richard Todd Back · [dytuk.media/shazamlite](https://dytuk.media/shazamlite)
