1
1
Fork
You've already forked discogs
0
A set of scripts to organize music files (FLAC) based on properly tagged (Discogs) data. Normalize filenames and folder structure, make sure releases can be identified reliably.
  • Python 86.2%
  • HTML 8.4%
  • Shell 3%
  • Dockerfile 2.4%
Frank Köhntopp 5f395b8257 Add LRC metadata headers from FLAC tags to all LRC lyrics
For every track with LRC lyrics, rebuild [ar:], [ti:], [al:], [length:]
headers from the actual FLAC tags (ARTIST, TITLE, ORIGINAL_TITLE, track
length). Strips any existing headers first so lrclib-provided ones are
replaced with accurate values. New action 'header' logged at INFO.
Album name uses ORIGINAL_TITLE (original Discogs title, not enriched ALBUM).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026年06月21日 15:09:00 +02:00
favicon UI polish, lyrics rewrite, syslog, config fixes 2026年06月20日 18:35:29 +02:00
templates assets for web ui 2026年06月04日 22:26:55 +02:00
.dockerignore Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
.gitignore Fix .gitignore and remove infrastructure/data files from tracking 2026年06月20日 18:48:20 +02:00
00_todo.txt gitignore update 2026年02月01日 09:34:13 +01:00
album_list.py Fold lyrics export into the existing album scan pass 2026年06月21日 11:02:00 +02:00
albums_static.html create csv with album data for html list (initial) 2026年02月01日 08:54:50 +01:00
bliss.py Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
build_synology.sh Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
calculate_dr.py Switch logging to structlog; drop timelog; fix Docker TagLib build 2026年06月07日 16:42:26 +02:00
calculate_fp.py Switch logging to structlog; drop timelog; fix Docker TagLib build 2026年06月07日 16:42:26 +02:00
CLAUDE.md Update CLAUDE.md and README.md to current state 2026年06月20日 18:56:24 +02:00
config_demo.py UI polish, lyrics rewrite, syslog, config fixes 2026年06月20日 18:35:29 +02:00
convert_opus.py Switch logging to structlog; drop timelog; fix Docker TagLib build 2026年06月07日 16:42:26 +02:00
docker-compose-synology.yml Switch logging to structlog; drop timelog; fix Docker TagLib build 2026年06月07日 16:42:26 +02:00
Dockerfile Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
fixtags.py Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
INSTALL.md Change host port to 8765 in INSTALL.md 2026年06月20日 19:04:30 +02:00
log.py UI polish, lyrics rewrite, syslog, config fixes 2026年06月20日 18:35:29 +02:00
lyricscloud.py added code comments through Claude 2026年03月04日 12:38:15 +01:00
mcp_albums.py Export lyrics to config/lyrics/ during album scan; add MCP lyrics tools 2026年06月21日 11:00:43 +02:00
nzbfix.py Web UI improvements, Docker hardening, rclone rework 2026年06月10日 17:00:37 +02:00
README.md Update CLAUDE.md and README.md to current state 2026年06月20日 18:56:24 +02:00
requirements.txt cleanup 2026年02月01日 09:04:49 +01:00
rsgain.ini rsgain refinements (depends on config file!) 2026年05月21日 16:26:59 +02:00
SPEC.md added code comments through Claude 2026年03月04日 12:38:15 +01:00
update_gitignore.sh Back to taglib for everything 2024年11月16日 23:11:22 +01:00
update_lyrics.py Add LRC metadata headers from FLAC tags to all LRC lyrics 2026年06月21日 15:09:00 +02:00
uv.lock cleanup 2026年02月01日 09:04:49 +01:00
webui.py UI polish, lyrics rewrite, syslog, config fixes 2026年06月20日 18:35:29 +02:00

Discogs Music Library Manager

A collection of Python scripts and a web UI for managing a local FLAC music library using Discogs metadata.

Core philosophy: tags are set by the user via a dedicated tagger (e.g. Yate on macOS). Scripts enrich and organise — they never overwrite user-set tags arbitrarily. The DISCOGS_RELEASE_ID tag anchors every album to an exact Discogs release, eliminating the ambiguity that automated taggers introduce.

Why?

If you have multiple versions of the same album (original, remaster, SACD, Qobuz 24/96), automated music tools will happily collapse them into one. I've tried many; they've all mangled my collection at some point. Assigning a Discogs release ID to every album means I always know exactly which version I'm listening to, and can recover from any accidental tag overwrite as long as the release ID survives.

Features

  • Web UI — FastAPI + HTMX interface: browse your library, trigger scans, fetch lyrics, organise files, sync to remote
  • Configurable link buttons — up to 5 toolbar buttons linking to any URL (favicons auto-cached)
  • Tag enrichment — pulls release date, original release date, and format info from the Discogs API
  • File organisation — moves FLACs into Artist/Album/track_title.flac, creates MP3 mirrors via ffmpeg
  • Dynamic Range scoring — per-track and per-album DR values written as FLAC tags; DR column links to loudness-war.info
  • Lyrics — parallel fetching (32 workers) from lrclib.net; LRC upgrade and invalid-LRC detection
  • AcoustID fingerprinting — generates and stores acoustic fingerprints
  • rclone sync — mirrors the FLAC library to a remote destination
  • Syslog forwarding — optional structured log forwarding to a Synology log server
  • Docker support — runs on Docker Desktop (Mac) or Synology NAS

Quick Start

Local (macOS)

brew install taglib --HEAD ffmpeg rsgain rclone
cp config_demo.py config/config.py # fill in your paths and API key
uv run webui.py

Open http://localhost:8000

Docker (local)

Create docker-compose.yml (gitignored — may contain credentials):

services:discogs:build:.ports:- "8000:8000"volumes:- ./config:/config- /path/to/flac:/flacenvironment:- CONFIG_DIR=/config- PORT=8000- RCLONE_CONFIG=/config/rclone.conf
docker compose up --build

Synology NAS

./build_synology.sh # builds discogs-synology-amd64.tar
# Upload via Container Manager → Image → Add → Import from file

Then use docker-compose-synology.yml as a reference for container settings.

Configuration

Copy config_demo.py to config/config.py and set:

Key Description
discogs_api_key From https://www.discogs.com/settings/developers
flacroot Root of your organised FLAC library (container-internal path)
mp3root MP3 mirror root
nzbdir Staging directory for newly tagged FLACs
flacroot_local Path as seen by the browser (for tagger deep links)
flacroot_remote rclone destination remote (e.g. ROCK:/mnt/flac)
rclone_source rclone source remote (e.g. FLAC:/flac)
syslog_host / syslog_port Optional Synology log server
log_file Log filename (written to config_dir)

All config values are also editable via the Settings modal in the web UI.

config.py is gitignored — it contains credentials.

Tagging Suggestions

  • Assign a Discogs release ID and a MusicBrainz ID for every album
  • Add decent cover art
  • Put source info (vendor, medium) in DESCRIPTION (e.g. "Qobuz 24/96")
  • For ambiguous titles or deluxe editions, put the disambiguation in ORIGINAL_FILENAME
  • Use SUBTITLE for format variants (e.g. "SACD", "5.1")

Typical Workflow

  1. Tag FLAC files with a Discogs Release ID using Yate or similar
  2. Drop files into nzbdir (staging)
  3. Run nzbfix.py (or click Refresh in the web UI) to enrich tags, calculate DR, generate fingerprints, fetch lyrics, and organise files into the library
  4. Use the web UI to browse, search, and manage the library

Scripts

Script Purpose
webui.py Web interface (FastAPI + HTMX)
nzbfix.py Pipeline orchestrator
fixtags.py Discogs API tag enrichment
bliss.py File organisation + MP3 sync
album_list.py Album inventory scan → CSV + DR chart
update_lyrics.py Parallel lyrics fetch from lrclib.net (32 workers)
calculate_dr.py Dynamic Range calculation
calculate_fp.py AcoustID fingerprint generation
convert_opus.py FLAC → Opus transcoding
build_synology.sh Build Docker image tar for Synology upload

All scripts use uv and declare their own dependencies via PEP 723 headers — no manual pip install needed:

uv run fixtags.py /path/to/album

Requirements

  • Python ≥ 3.14 (managed automatically by uv)
  • TagLib 2.x — built from source in Docker; brew install taglib --HEAD on macOS
  • ffmpeg, rsgain, rclone — included in the Docker image; install separately for local use

Logging

Structured logging via structlog:

  • Pretty coloured output when running in a terminal
  • JSON to stdout when running as a subprocess (captured and re-logged cleanly by the web UI)
  • JSON log file at config_dir/log_file
  • Optional syslog forwarding: set syslog_host and syslog_port in config.py
  • Set LOG_LEVEL env var to control verbosity (default: INFO)

Libraries and Tools