From 5c7b6759ff9da2fc10774c8e0d98732a3a7474b8 Mon Sep 17 00:00:00 2001 From: dschlueter Date: Wed, 29 Apr 2026 06:03:39 +0200 Subject: [PATCH] Update README: Ollama/OpenRouter LLM, OCR, YouTube, WebP, underscore schema MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- README.md | 97 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index de4ca73..e8a6803 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ 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 optionaler Claude-KI für lückenhafte Metadaten. +API-Key nutzbar, mit lokalem LLM (Ollama) für lückenhafte Metadaten. --- @@ -12,13 +12,20 @@ API-Key nutzbar, mit optionaler Claude-KI für lückenhafte Metadaten. - **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 -- **Claude API** — Reasoning-Schritt für unklare / widersprüchliche Daten (optional) -- **Cover-Art** — lokal → MusicBrainz Cover Art Archive → einbetten in MP3/FLAC/M4A +- **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** — `01 - Artist - Title.ext` / `2-07 - Artist - Title.ext` (Multi-CD) +- **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 @@ -29,8 +36,9 @@ API-Key nutzbar, mit optionaler Claude-KI für lückenhafte Metadaten. ```bash pip install mutagen musicbrainzngs pyacoustid discogs_client \ - anthropic Pillow requests tqdm + 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? | @@ -39,21 +47,28 @@ sudo apt install libchromaprint-tools # fpcalc für AcoustID-Fingerprinting | `musicbrainzngs` | MusicBrainz-API | ja | | `pyacoustid` | AcoustID-Fingerprinting | ja | | `discogs_client` | Discogs-API | ja | -| `anthropic` | Claude API | ja | -| `Pillow` | Cover-Bildgröße prüfen | 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 | -|----------|-------------| -| `ANTHROPIC_API_KEY` | Claude API (Reasoning für Metadaten-Lücken) | -| `ACOUSTID_API_KEY` | AcoustID-Fingerprinting | -| `DISCOGS_TOKEN` | Discogs-API | +| 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 | – | --- @@ -74,7 +89,7 @@ music_enricher.py --album PFAD [Optionen] | `--backup PFAD` | Backup-Verzeichnis vor Änderungen | | `--report PFAD` | CSV-Report der Änderungen | | `--no-fingerprint` | AcoustID-Fingerprinting überspringen | -| `--no-api` | Keine externen API-Calls | +| `--no-api` | Keine externen API-Calls (MusicBrainz, Discogs, OCR) | | `--no-cover` | Kein Cover-Art-Download | | `--album PFAD` | Einzelnes Album verarbeiten | | `--no-tqdm` | Fortschrittsanzeige deaktivieren | @@ -84,11 +99,11 @@ music_enricher.py --album PFAD [Optionen] ## Verwendung ```bash -# Einzelnes Album — Dry-Run, kein API-Key nötig +# Einzelnes Album — Dry-Run, nur lokale Analyse python3 music_enricher.py --dry-run --no-api \ --album ~/Musik/Abba_-_Greatest_Hits -# Mit MusicBrainz-Lookup +# Mit MusicBrainz-Lookup und Ollama-LLM python3 music_enricher.py --dry-run \ --album ~/Musik/Bach_Organ_-_Peter_Hurford @@ -100,12 +115,12 @@ python3 music_enricher.py --embed-cover --rename \ # Auto-Modus: nur Vorschläge ≥ 90% Konfidenz anwenden python3 music_enricher.py --auto --confidence 0.90 \ - --embed-cover --backup /tmp/backup \ + --embed-cover --rename --backup /tmp/backup \ ~/Musik -# Mit Claude API (ANTHROPIC_API_KEY setzen) -export ANTHROPIC_API_KEY=sk-ant-... -python3 music_enricher.py --dry-run --album ~/Musik/UnbekanntesAlbum +# 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 ``` --- @@ -116,30 +131,32 @@ python3 music_enricher.py --dry-run --album ~/Musik/UnbekanntesAlbum Album-Verzeichnis │ ▼ -1. AlbumScanner — Dateitypen klassifizieren +1. AlbumScanner — Dateitypen klassifizieren (Audio, Bild, Tracklist, Playlist) │ ▼ 2. HintExtractor — lokal, keine API ├─ Verzeichnisname → Artist, Album, Jahr - ├─ Dateinamen → Tracknummer, Artist, Titel + ├─ Dateinamen → Tracknummer, Artist, Titel (YouTube-ID wird entfernt) ├─ ID3/FLAC-Tags → bestehende Werte - └─ Tracklist .txt → Tracklisten parsen + ├─ 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 - └─ Claude API → Reasoning-Schritt (optional) + └─ LLM-Reasoning → Ollama lokal → OpenRouter (DeepSeek V3) │ ▼ -4. CoverHandler — lokal → MusicBrainz → einbetten +4. CoverHandler — lokal (JPG/PNG/WebP) → MusicBrainz → einbetten │ ▼ -5. ReviewStep — interaktiv oder --auto mit Konfidenz +5. ReviewStep — interaktiv oder --auto mit Konfidenz-Schwellwert │ ▼ -6. Executor — Backup → Tags → Cover → Umbenennen → Report +6. Executor — Backup → Tags → Cover → Umbenennen → M3U → Report ``` --- @@ -152,20 +169,28 @@ Album-Verzeichnis | MusicBrainz via Fingerprint | +0.25 | | MusicBrainz-Texttreffer (Score/100) | +0.30 × Score | | Discogs | +0.15 | -| Claude-Reasoning | +0.10 | -| Lokale Hints (Ordner-/Dateiname) | +0.05 | +| 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 - Bach - Toccata And Fugue In D Minor BWV 565.flac +01_-_ABBA_-_Dancing_Queen.mp3 +2-07_-_Die_Bergvagabunden_-_Hohe_Tannen.flac ``` -Bei Single-Disc entfällt die Disc-Nummer. Bei Multi-CD-Alben (Unterordner `CD1/`, `CD2/` etc.) -wird die Disc-Nummer automatisch erkannt. +**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.). --- @@ -176,10 +201,10 @@ 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-Auswertung -├── metadata_resolver.py MusicBrainz + Discogs + Claude API -├── cover_handler.py Cover-Art: Suche, Download, Einbettung -├── executor.py Backup, Tag-Schreiben, Umbenennen, CSV-Report +├── 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 ```