This script repurposes the star ratings in Navidrome by aligning them with Deezer's track rank. It fetches the Deezer popularity rank (0β1,000,000+) for each track via the public search API and maps it to a 1β5 star rating. Higher rank = more popular on Deezer. No API key is required β the Deezer API is completely open.
This is a fork of krestaino/sptnr by Kevin Restaino, which originally used Spotify's popularity score. This fork replaces Spotify with Deezer's public API, removing the need for OAuth, client secrets, or any authentication.
- Features
- Requirements
- Quick Start (GHCR pre-built image)
- Building from this fork
- Using Docker Compose
- Running Natively (Python)
- Usage
- Examples
- Resuming Interrupted Sessions
- Managing Docker Containers
- Mapping Deezer Rank to Navidrome Ratings
- Estimated Processing Times
- Importance of Accurate Metadata for Track Lookup
- Logs
- CI/CD (GitHub Actions)
- Credits
- Deezer Integration: Uses the public Deezer Search API (
api.deezer.com/search) β no API key or authentication needed. - Navidrome Integration: Updates track ratings in Navidrome based on Deezer's popularity rank.
- Flexible Processing: Process specific artists, albums, or a range of artists or albums.
- Preview Mode: Run the script in preview mode to see changes without making any actual updates.
- Logging: Detailed logging of the process, both in the console and to a file.
- Docker Support: Pre-built image available on GitHub Container Registry (GHCR) with multi-arch support (amd64 + arm64).
- Docker or Python 3.x
- Access to a Navidrome server
- No API keys or external accounts required (Deezer API is public)
Compatibility Note: While this script was built with Navidrome in mind, it should theoretically work on any Subsonic server.
The easiest way to run dztnr is using the pre-built Docker image published to GitHub Container Registry on every push to main. It supports both linux/amd64 and linux/arm64.
docker run -t --rm \
-e NAV_BASE_URL=https://your_navidrome.example.com \
-e NAV_USER=your_navidrome_username \
-e NAV_PASS=your_navidrome_password \
ghcr.io/scatolo/dztnr:latestTo pin a specific version (check packages for available tags):
docker run -t --rm \
-e NAV_BASE_URL=https://your_navidrome.example.com \
-e NAV_USER=your_navidrome_username \
-e NAV_PASS=your_navidrome_password \
ghcr.io/scatolo/dztnr:1.3.0Tip: Use
--rmto auto-remove the container when it finishes. If you want persistent logs, add-v ./logs:/usr/src/app/logs.
First run? Start in preview mode with a single artist to test connectivity:
docker run -t --rm \
-e NAV_BASE_URL=https://your_navidrome.example.com \
-e NAV_USER=your_admin_user \
-e NAV_PASS=your_admin_password \
ghcr.io/scatolo/dztnr:latest -p -l 1(-p = preview, no writes; -l 1 = only the first artist)
This is a fork of krestaino/sptnr. The main changes are:
- Deezer instead of Spotify β no OAuth, no client ID/secret, no API key
- Rating based on Deezer rank instead of Spotify popularity
- Rate limiting at 0.2s per API call
- Pre-built images published to GHCR via GitHub Actions
git clone https://github.com/scatolo/dztnr.git
cd dztnr
docker build -t dztnr-local .
docker run -t --rm \
-e NAV_BASE_URL=https://your_navidrome.example.com \
-e NAV_USER=your_navidrome_username \
-e NAV_PASS=your_navidrome_password \
dztnr-localgit clone https://github.com/scatolo/dztnr.git
cd dztnr
cp .env.example .env
# Edit .env with your Navidrome URL and credentials
pip install -r requirements.txt
python dztnr.py -p -l 1 # preview mode, first artist only-
Create
docker-compose.yml: copydocker-compose.yml.exampleand fill in your Navidrome details.Using the pre-built GHCR image (recommended):
version: "3.8" services: dztnr: container_name: dztnr image: ghcr.io/scatolo/dztnr:latest environment: - NAV_BASE_URL=https://your_navidrome.example.com - NAV_USER=your_navidrome_username - NAV_PASS=your_navidrome_password volumes: - ./logs:/usr/src/app/logs
Or build locally:
version: "3.8" services: dztnr: container_name: dztnr build: . environment: - NAV_BASE_URL=https://your_navidrome.example.com - NAV_USER=your_navidrome_username - NAV_PASS=your_navidrome_password volumes: - ./logs:/usr/src/app/logs
-
Run the script:
docker-compose run --rm dztnrWith options:
docker-compose run --rm dztnr -p -l 1
-
Clone the repository or download the necessary files (
dztnr.py,requirements.txt,.env.example). -
Install dependencies:
pip install -r requirements.txt -
Configure environment variables. Rename
.env.exampleto.envand fill in your Navidrome credentials:cp .env.example .env # Edit .env β only NAV_BASE_URL, NAV_USER, NAV_PASS are needed -
Run the script:
python dztnr.py [options]
| Flag | Long form | Description |
|---|---|---|
-p |
--preview |
Preview mode β no changes written to Navidrome |
-a |
--artist ID |
Process a specific artist by Navidrome ID (repeatable) |
-b |
--album ID |
Process a specific album by Navidrome ID (repeatable) |
-s |
--start N |
Start processing from artist at index N (0-based) |
-l |
--limit N |
Process at most N artists from the start index |
-v |
--version |
Print version and exit |
| Method | Command |
|---|---|
| GHCR image | docker run -t --rm -e NAV_BASE_URL=... -e NAV_USER=... -e NAV_PASS=... ghcr.io/scatolo/dztnr:latest [options] |
| Local Docker | docker run -t --rm -e NAV_BASE_URL=... -e NAV_USER=... -e NAV_PASS=... dztnr-local [options] |
| Docker Compose (GHCR) | docker-compose run --rm dztnr [options] |
| Python | python dztnr.py [options] |
See what would be updated without making changes:
python dztnr.py -pdocker-compose run --rm dztnr -ppython dztnr.py -a <navidrome_artist_id>docker run -t --rm -e NAV_BASE_URL=... -e NAV_USER=... -e NAV_PASS=... ghcr.io/scatolo/dztnr:latest -a <navidrome_artist_id>Start from artist #10 and process the next 5:
python dztnr.py -s 10 -l 5python dztnr.py -b <album_id_1> -b <album_id_2>If the session gets interrupted (network error, machine sleep, etc.), you can resume from where you left off.
Check the log file for the last processed artist. The log entry contains the index in brackets: Artist: ARTIST_NAME (ARTIST_ID)[INDEX].
Restart with -s INDEX:
python dztnr.py -s 42docker run -t --rm -e ... ghcr.io/scatolo/dztnr:latest -s 42docker run and docker-compose run create a new container each time. Use --rm to auto-remove them on exit, or clean up manually:
docker container pruneWarning: This removes all stopped containers on your system. Check with docker ps -a first.
The script translates Deezer's popularity rank into Navidrome's 5-star rating system:
| Deezer Rank | Rating | Description |
|---|---|---|
| 0 β 9,999 | 0 | Unknown / Niche |
| 10,000 β 99,999 | 1 | Low popularity |
| 100,000 β 299,999 | 2 | Moderately popular |
| 300,000 β 599,999 | 3 | Popular |
| 600,000 β 849,999 | 4 | Very popular |
| 850,000+ | 5 | Globally known |
With a time.sleep(0.2) delay between Deezer API calls:
| Library Size (Tracks) | Estimated Time |
|---|---|
| 1,000 | ~5 minutes |
| 5,000 | ~25 minutes |
| 10,000 | ~50 minutes |
| 50,000 | ~4 hours |
| 100,000 | ~8 hours |
These estimates assume a stable network connection. Actual times may vary.
The script searches Deezer using the query artist + track. Deezer's search is fairly forgiving, but accurate artist and track titles significantly improve the match rate. Tag your music library with MusicBrainz for best results.
Logs are stored in the logs/ directory. Each execution creates a new log file named deezer-rank_<timestamp>.log. Delete old logs manually if needed.
r:450000 β β
:3 | Song Title
r:<number>β Deezer rank (0β1,000,000+), or??if not foundβ β :<rating>β Navidrome star rating assigned (0β5)
- Green β Track matched and processed
- Red β Track not found on Deezer (
??)
Colors are terminal-only and stripped from log files.
On every push to main, a GitHub Actions workflow (.github/workflows/docker-ghcr.yml) builds a multi-arch Docker image (linux/amd64 + linux/arm64) tagged with the version from the VERSION file and latest, then pushes it to GitHub Container Registry at ghcr.io/scatolo/dztnr.
Pull requests also trigger a build (amd64 only, no push) to validate the Dockerfile.
Available tags: github.com/scatolo/dztnr/pkgs/container/dztnr
This project is a fork of krestaino/sptnr by Kevin Restaino, who originally created the script to sync Spotify popularity with Navidrome ratings. This fork adapts the codebase to use Deezer's public API instead, removing the need for any authentication or API keys while preserving all the original Navidrome integration logic, CLI flags, and Docker support.
