a self-hosted web app to download your own Qobuz library into Navidrome, then review, tag, de-duplicate, and file it.
  • Python 63.8%
  • JavaScript 20.7%
  • CSS 9%
  • Kotlin 4.7%
  • HTML 1.2%
  • Other 0.6%
Find a file
eldr 8dfa4b4b73 Initial commit — Quaver
Self-hosted Qobuz downloader & Navidrome library manager: download albums
and discographies as hi-res FLAC, with a review/tag/de-dupe/file workflow,
Last.fm recs, in-library badges, auth, persistent queue, and Docker deploy.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 14:55:55 +02:00
android Initial commit — Quaver 2026-06-12 14:55:55 +02:00
backend Initial commit — Quaver 2026-06-12 14:55:55 +02:00
deploy Initial commit — Quaver 2026-06-12 14:55:55 +02:00
frontend Initial commit — Quaver 2026-06-12 14:55:55 +02:00
tests Initial commit — Quaver 2026-06-12 14:55:55 +02:00
.dockerignore Initial commit — Quaver 2026-06-12 14:55:55 +02:00
.env.example Initial commit — Quaver 2026-06-12 14:55:55 +02:00
.gitignore Initial commit — Quaver 2026-06-12 14:55:55 +02:00
docker-compose.yml Initial commit — Quaver 2026-06-12 14:55:55 +02:00
Dockerfile Initial commit — Quaver 2026-06-12 14:55:55 +02:00
LICENSE Initial commit 2026-06-12 14:35:46 +02:00
pytest.ini Initial commit — Quaver 2026-06-12 14:55:55 +02:00
README.md Initial commit — Quaver 2026-06-12 14:55:55 +02:00
run.sh Initial commit — Quaver 2026-06-12 14:55:55 +02:00

Quaver 🎵

A self-hosted web app for downloading albums and full artist discographies from your own Qobuz account into a Navidrome-friendly FLAC library — then reviewing, tagging, de-duplicating, and filing them.

Requires an active Qobuz subscription. This uses your own credentials to download your own music for offline/local listening, which Qobuz permits.

How it works

  • On startup it scrapes the Qobuz web-player bundle for the current app_id and signing secrets (so it survives Qobuz rotating them), then logs in with your credentials to obtain a user_auth_token.

  • Search albums or artists, queue a single album or a whole discography.

  • Tracks are requested at the highest quality your tier allows (up to 24-bit/192kHz FLAC), streamed to disk, tagged with mutagen, and filed as:

    MUSIC_DIR/<Album Artist>/<Album Title> (Year)/NN - Title.flac
    

    Multi-disc albums prefix the filename with the disc number, and a cover.jpg is saved alongside plus embedded in each file.

Setup

cp .env.example .env       # then fill in QOBUZ_AUTH_TOKEN (or email/password) + MUSIC_DIR
./run.sh                   # creates a venv, installs deps, starts the server

Open http://127.0.0.1:8000.

cp .env.example .env       # fill it in; set MUSIC_DIR to your library path
docker compose up -d --build

.env, the SQLite queue (./data), and your music library are mounted as volumes, so rebuilds/redeploys never touch them. Published on 127.0.0.1:8000 for nginx to proxy. To deploy an update: git pull && docker compose up -d --build.

Tests

pip install -r backend/requirements-dev.txt
pytest        # unit tests for signing, the bundle regexes, validation,
              # library matching, auth, import parsing, and persistence

To reach it from your phone on the LAN, set HOST=0.0.0.0 in .env. It has no auth of its own — keep it behind your VPN / reverse proxy / Tailscale, not on the open internet, since it holds your Qobuz session.

Layout

backend/app/
  main.py          FastAPI routes + serves the UI
  config.py        settings from .env
  qobuz/
    spoofer.py     scrapes app_id + secrets from the web bundle
    client.py      login, search, metadata, signed file URLs
  downloader.py    async job queue: fetch → tag → file
  tagger.py        FLAC tagging + path layout
frontend/          vanilla HTML/CSS/JS UI

Optional integrations

Both are off unless their .env vars are set; the app runs fine without them.

Last.fm — "For You" recommendations. Set LASTFM_API_KEY (free, from last.fm/api) and LASTFM_USERNAME. A ★ For You button appears in the header. Since Last.fm's own recommendation endpoint is retired, it derives picks from your top artists/tracks → their similar artists/tracks, then resolves each to Qobuz so you can download it. Cached for an hour; ↻ Refresh forces a rebuild.

Navidrome — in-library badges. Set NAVIDROME_URL, NAVIDROME_USERNAME, NAVIDROME_PASSWORD. The app indexes your library over the Subsonic API and marks albums already present with a green "✓ In library" badge (refreshed every 15 min; POST /api/library/refresh forces it). Matching is album-level by normalized artist + album name (edition/remaster suffixes stripped).

Format ids

MAX_FORMAT_ID in .env: 27 = 24/192 (default), 7 = 24/96, 6 = 16/44 CD FLAC, 5 = MP3 320. Qobuz returns the best available up to your request.