Self-hosted music discovery pipeline with Navidrome, ListenBrainz, and Slskd
https://github.com/jordojordo/resonance.git
Resonance is a self-hosted music discovery pipeline that automatically finds and downloads music based on your listening habits and existing library. It combines multiple discovery sources into a unified approval workflow with a modern web UI.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RESONANCE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Your Music Library Your Listening History โ
โ (Navidrome/etc) (ListenBrainz scrobbles) โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโโ โ
โ โ Catalog โ โ lb-fetch โ โ
โ โ Discovery โ โ โ โ
โ โ (Last.fm) โ โ(ListenBrainz) โ
โ โโโโโโโฌโโโโโโ โโโโโโโโฌโโโโโโ โ
โ โ โ โ
โ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Pending Queue โโโโโโ Web UI (approve/reject) โ
โ โ (unified approval) โ โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ slskd-downloader โ โ
โ โ (Soulseek P2P) โ โ
โ โโโโโโโโโโโโฌโโโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Downloaded Music โโโโโโโโบ Your Music Library โ
โ โโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
mkdir -p resonance/data
cd resonance
Create config.yaml:
# See examples/config.yaml for full configuration options
# ListenBrainz recommendations (based on listening history)
listenbrainz:
username: "your_username"
token: "your_token" # From https://listenbrainz.org/settings/
approval_mode: "manual" # "auto" or "manual"
mode: album # "album" or "track"
fetch_count: 100
# slskd connection
slskd:
host: "http://slskd:5030"
api_key: "your_slskd_api_key"
# Optional: Advanced search configuration (see docs/configuration.md)
# search:
# album_query_template: "{artist} {album}"
# exclude_terms: ["live", "remix", "cover"]
# retry:
# enabled: true
# max_attempts: 3
# Catalog discovery (based on library artists โ Last.fm similar)
catalog_discovery:
enabled: true
navidrome:
host: "http://navidrome:4533"
username: "your_username"
password: "your_password"
lastfm:
api_key: "your_lastfm_api_key"
max_artists_per_run: 10
min_similarity: 0.3
mode: "manual"
# Avoid downloading albums you already own (Optional)
library_duplicate:
enabled: true
# Auto-reject items that already exist in your library
auto_reject: false
# Web UI settings
ui:
auth:
enabled: true
type: "basic" # "basic", "api_key", or "proxy"
username: "admin"
password: "changeme" # Change this!
Create docker-compose.yaml:
services:
resonance:
image: ghcr.io/jordojordo/resonance:latest
container_name: resonance
volumes:
- ./config.yaml:/config/config.yaml:ro
- ./data:/data
ports:
- "8080:8080"
restart: unless-stopped
docker compose up -d
Open http://localhost:8080 and log in with your configured credentials.
Fetches track recommendations from ListenBrainz based on your listening history (scrobbles). Recommendations are resolved to albums via MusicBrainz.
How it works:
Finds new artists similar to ones you already own using Last.fm's similarity data.
How it works:
See docs/configuration.md for full configuration options.
The web UI provides:
Resonance includes built-in authentication options:
ui:
auth:
enabled: true
type: "basic" # HTTP Basic Auth
username: "admin"
password: "secure_password"
Or use API key authentication:
ui:
auth:
enabled: true
type: "api_key"
api_key: "your_secret_api_key"
For advanced authentication (SSO, 2FA, LDAP), integrate with Authelia via your reverse proxy. See docs/authelia-integration.md.
Resonance exposes a REST API for automation and integration:
GET /api/v1/queue/pending # List pending items
POST /api/v1/queue/approve # Approve items
POST /api/v1/queue/reject # Reject items
POST /api/v1/actions/lb-fetch # Trigger lb-fetch
POST /api/v1/actions/catalog # Trigger catalog discovery
GET /api/v1/library/stats # Library sync statistics
POST /api/v1/library/sync # Trigger library sync
POST /api/v1/library/organize # Trigger library organize
GET /api/v1/library/organize/status # Library organize status
GET /api/v1/health # Health check
See docs/api.md for full API documentation.
Resonance runs as a single Node.js process with background jobs scheduled via node-cron:
| Job | Schedule | Purpose |
|---|---|---|
| lb-fetch | Every 6 hours | ListenBrainz recommendations |
| catalog-discovery | Weekly | Last.fm similar artists |
| slskd-downloader | Every hour | Process wishlist via slskd |
| library-sync | Daily | Sync Navidrome library albums |
| library-organize | Manual (default) | Move completed downloads into library |
See docs/architecture.md for technical details.
| Variable | Default | Description |
|---|---|---|
PORT | 8080 | HTTP server port |
LOG_LEVEL | info | Logging verbosity |
LOG_TO_CONSOLE | true | Log to stdout/stderr |
LOG_TO_FILE | false | Log to files in LOG_DIR |
LOG_DIR | DATA_PATH | Directory for log files (when enabled) |
LB_FETCH_INTERVAL | 21600 | Seconds between lb-fetch runs (6h) |
CATALOG_INTERVAL | 604800 | Seconds between catalog discovery (7d) |
SLSKD_INTERVAL | 3600 | Seconds between download runs (1h) |
RUN_JOBS_ON_STARTUP | true | Run discovery jobs immediately on startup |
LIBRARY_SYNC_INTERVAL | 86400 | Seconds between library sync runs (24h) |
LIBRARY_ORGANIZE_INTERVAL | 0 | Seconds between library organize runs (0 = manual only) |
All state is stored in /data:
/data/
โโโ resonance.sqlite # SQLite database (queue, processed items, etc.)
โโโ wishlist.txt # Albums to download (read by slskd-downloader)
Resonance needs network access to:
| Service | Purpose |
|---|---|
| slskd | Queue downloads |
| Navidrome | Scan library artists |
| api.listenbrainz.org | Fetch recommendations |
| ws.audioscrobbler.com | Last.fm similar artists |
| musicbrainz.org | Album metadata |
| coverartarchive.org | Album artwork |
| api.deezer.com | Audio previews (default) |
| api.spotify.com | Audio previews (optional fallback) |
git clone https://github.com/jordojordo/resonance.git
cd resonance
docker build -t resonance .
pnpm --filter server install
pnpm --filter ui install
pnpm dev # Starts on http://localhost:5173, runs UI and server in parallel
See CONTRIBUTING.md for development guidelines.
Apache License 2.0 - See LICENSE for details.