Music_Metadata_Enricher/README.md
dschlueter 5c7b6759ff Update README: Ollama/OpenRouter LLM, OCR, YouTube, WebP, underscore schema
- Replace Claude API references with Ollama → OpenRouter chain
- Add YouTube ID detection, OCR back cover, WebP cover support
- Fix filename schema examples (spaces → underscores, _-_ separator)
- Add classical naming schema with Performer/Composer distinction
- Add Ollama env vars (OLLAMA_HOST, OLLAMA_RESOLVE_MODEL, OLLAMA_OCR_MODEL)
- Update pipeline diagram with OCR and YouTube steps
- Add yt-dlp to prerequisites

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 06:03:39 +02:00

229 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Music Metadata Enricher
KI-gestützter Musik-Metadaten-Enricher für Jellyfin-Bibliotheken.
Analysiert Album-Verzeichnisse, vervollständigt Tags, besorgt Cover-Art und
benennt Dateien optional nach einem einheitlichen Schema um — vollständig ohne
API-Key nutzbar, mit lokalem LLM (Ollama) für lückenhafte Metadaten.
---
## Features
- **Lokale Analyse** — Verzeichnisname, Dateinamen, bestehende ID3/FLAC/M4A-Tags,
Tracklist-Textdateien (.txt, .htm, .html)
- **YouTube-ID-Erkennung** — erkennt YouTube-Video-IDs im Dateinamen, holt Titel,
Uploader und Kapitel automatisch via `yt-dlp`
- **OCR Back-Cover** — liest Tracklisten aus `back.jpg` / Booklet-Bildern via
Ollama Vision (qwen3-vl, minicpm-v)
- **MusicBrainz-Lookup** — Textsuche + AcoustID-Fingerprinting (optional)
- **Discogs-Fallback** — bei MusicBrainz-Misses
- **LLM-Reasoning** — Ollama (lokal, kostenlos) → OpenRouter (DeepSeek V3) für
unklare / widersprüchliche Metadaten
- **Cover-Art** — lokal (JPG/PNG/WebP) → MusicBrainz Cover Art Archive → einbetten
in MP3/FLAC/M4A; WebP wird automatisch zu JPEG konvertiert
- **Tag-Schreiben** — title, artist, album, albumartist, tracknumber, discnumber,
date, genre, label (mutagen, ID3v2.4)
- **Umbenennen** — normiertes Dateinamen-Schema mit Unterstrichen (Pop und Klassik)
- **M3U-Playlist** — wird nach dem Umbenennen automatisch neu generiert
- **Backup** — Sicherungskopien vor jeder Änderung
- **CSV-Report** — vollständiges Protokoll aller Änderungen
- **Interaktiver / Auto-Modus** — mit Konfidenz-Schwellwert
---
## Voraussetzungen
```bash
pip install mutagen musicbrainzngs pyacoustid discogs_client \
Pillow requests tqdm beautifulsoup4
sudo apt install libchromaprint-tools # fpcalc für AcoustID-Fingerprinting
sudo apt install yt-dlp # YouTube-Metadaten (optional)
```
| Paket | Zweck | Optional? |
|-------|-------|-----------|
| `mutagen` | Tags lesen/schreiben | nein |
| `musicbrainzngs` | MusicBrainz-API | ja |
| `pyacoustid` | AcoustID-Fingerprinting | ja |
| `discogs_client` | Discogs-API | ja |
| `Pillow` | Cover-Bildgröße prüfen, WebP→JPEG | ja |
| `requests` | Cover-Art-Download | ja |
| `tqdm` | Fortschrittsbalken | ja |
| `beautifulsoup4` | HTML-Tracklisten parsen | ja |
| `fpcalc` | Audio-Fingerprinting-Binary | ja |
| `yt-dlp` | YouTube-Metadaten + Kapitel | ja |
Für LLM-Reasoning wird ein laufender **Ollama**-Server erwartet (Port 11434).
Empfohlenes Modell: `qwen3:8b` (5 GB). OCR: `qwen3-vl:latest`.
---
## Umgebungsvariablen (optional)
| Variable | Beschreibung | Default |
|----------|-------------|---------|
| `OLLAMA_HOST` | Ollama-Server-URL | `http://localhost:11434` |
| `OLLAMA_RESOLVE_MODEL` | LLM für Metadaten-Reasoning | `qwen3:8b` |
| `OLLAMA_OCR_MODEL` | Vision-Modelle für OCR (kommagetrennt) | `qwen3-vl:latest,minicpm-v:latest,deepseek-ocr:latest` |
| `OPENROUTER_API_KEY` | OpenRouter-Fallback (DeepSeek V3) | |
| `ACOUSTID_API_KEY` | AcoustID-Fingerprinting | |
| `DISCOGS_TOKEN` | Discogs-API | |
---
## CLI
```
music_enricher.py [Optionen] PFAD [PFAD ...]
music_enricher.py --album PFAD [Optionen]
```
| Option | Beschreibung |
|--------|-------------|
| `--dry-run` | Vorschläge anzeigen, nichts schreiben |
| `--auto` | Kein interaktiver Review-Schritt |
| `--confidence FLOAT` | Min-Konfidenz für `--auto` (default: 0.85) |
| `--rename` | Dateien nach Schema umbenennen |
| `--embed-cover` | Cover-Art in Audiodatei einbetten |
| `--backup PFAD` | Backup-Verzeichnis vor Änderungen |
| `--report PFAD` | CSV-Report der Änderungen |
| `--no-fingerprint` | AcoustID-Fingerprinting überspringen |
| `--no-api` | Keine externen API-Calls (MusicBrainz, Discogs, OCR) |
| `--no-cover` | Kein Cover-Art-Download |
| `--album PFAD` | Einzelnes Album verarbeiten |
| `--no-tqdm` | Fortschrittsanzeige deaktivieren |
---
## Verwendung
```bash
# Einzelnes Album — Dry-Run, nur lokale Analyse
python3 music_enricher.py --dry-run --no-api \
--album ~/Musik/Abba_-_Greatest_Hits
# Mit MusicBrainz-Lookup und Ollama-LLM
python3 music_enricher.py --dry-run \
--album ~/Musik/Bach_Organ_-_Peter_Hurford
# Vollständig: Tags + Cover einbetten + umbenennen, mit Backup und Report
python3 music_enricher.py --embed-cover --rename \
--backup /tmp/musik_backup \
--report report.csv \
~/Musik
# Auto-Modus: nur Vorschläge ≥ 90% Konfidenz anwenden
python3 music_enricher.py --auto --confidence 0.90 \
--embed-cover --rename --backup /tmp/backup \
~/Musik
# Album mit YouTube-IDs in Dateinamen (yt-dlp holt Titel + Kapitel automatisch)
python3 music_enricher.py --auto --confidence 0.1 --rename --embed-cover \
--album ~/Musik/Die_Bergvagabunden_Am_Lagefeuer.audio
```
---
## Verarbeitungs-Pipeline
```
Album-Verzeichnis
1. AlbumScanner — Dateitypen klassifizieren (Audio, Bild, Tracklist, Playlist)
2. HintExtractor — lokal, keine API
├─ Verzeichnisname → Artist, Album, Jahr
├─ Dateinamen → Tracknummer, Artist, Titel (YouTube-ID wird entfernt)
├─ ID3/FLAC-Tags → bestehende Werte
├─ Tracklist .txt/.htm → Tracklisten parsen (4-stufiges Matching)
├─ YouTube-IDs → Titel, Uploader, Kapitel via yt-dlp
└─ OCR Back-Cover → Tracklist aus back.jpg via Ollama Vision
3. MetadataResolver
├─ AcoustID → MusicBrainz via Fingerprint
├─ Textsuche → MusicBrainz-API
├─ Discogs → Fallback
└─ LLM-Reasoning → Ollama lokal → OpenRouter (DeepSeek V3)
4. CoverHandler — lokal (JPG/PNG/WebP) → MusicBrainz → einbetten
5. ReviewStep — interaktiv oder --auto mit Konfidenz-Schwellwert
6. Executor — Backup → Tags → Cover → Umbenennen → M3U → Report
```
---
## Konfidenz-Modell
| Quelle | Bonus |
|--------|-------|
| AcoustID-Match ≥ 90% | +0.20 |
| MusicBrainz via Fingerprint | +0.25 |
| MusicBrainz-Texttreffer (Score/100) | +0.30 × Score |
| Discogs | +0.15 |
| LLM-Reasoning (Ollama/OpenRouter) | +0.10 |
| Lokale Hints (Ordner-/Dateiname, YouTube) | +0.05 |
---
## Dateinamen-Schema (mit `--rename`)
**Pop/Default** — Leerzeichen als Unterstriche, Teile durch `_-_` getrennt:
```
01_-_ABBA_-_Dancing_Queen.mp3
2-07_-_Die_Bergvagabunden_-_Hohe_Tannen.flac
```
**Klassik** — Performer und Komponist explizit getrennt:
```
01_-_Peter_Hurford_-_Johann_Sebastian_Bach_-_Toccata_And_Fugue_In_D_Minor_BWV_565.mp3
01_-_Gardiner_-_Bach_-_Kantate_BWV_147_-_English_Baroque_Soloists.flac
```
Schema: `[D-]TT_-_Performer_-_Komponist_-_Werk[_-_Orchester_Dirigent].ext`
Bei Single-Disc entfällt die Disc-Nummer. Bei Multi-CD wird sie immer gesetzt (`1-01`, `2-01` etc.).
---
## Projektstruktur
```
Music_Metadata_Enricher/
├── music_enricher.py Haupt-CLI, Pipeline-Orchestrierung
├── models.py Dataclasses: AlbumScan, AlbumHints, TrackProposal, …
├── scanner.py Dateisystem-Scanner, Typ-Klassifikation
├── hint_extractor.py Dateiname/Tag/Tracklist/OCR/YouTube-Auswertung
├── metadata_resolver.py MusicBrainz + Discogs + Ollama/OpenRouter LLM
├── cover_handler.py Cover-Art: Suche, WebP-Konvertierung, Download, Einbettung
├── executor.py Backup, Tag-Schreiben, Umbenennen, M3U, CSV-Report
└── test_suite_enricher.py 17 Unit-/Integrationstests
```
---
## Tests
```bash
python3 test_suite_enricher.py
# 📊 17/17 Tests erfolgreich
```
---
## Unterstützte Formate
| Format | Tags | Cover-Einbettung |
|--------|------|-----------------|
| MP3 | ID3v2.4 (EasyID3) | APIC-Frame |
| FLAC | Vorbis-Comments | METADATA_BLOCK_PICTURE |
| M4A/AAC | MP4-Tags | covr-Atom |
| Sonstige | mutagen generic | |