docs: add re-apply, cleanup, and gen_json plans
- Re-apply: idempotent apply using track number prefix as stable anchor; album.json never touched; optional --rename-dir flag for dir renames - Cleanup: auto-remove abcde.* temp dirs after ripping + manual command - gen_json: reverse-engineer album.json from file tree using fixed naming convention; audio tags take priority over filenames for all fields Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6a7602387a
commit
5de6caba3a
1 changed files with 186 additions and 0 deletions
|
|
@ -335,3 +335,189 @@ class DiscMetadata:
|
|||
|
||||
Nach dem letzten `rip_disc`-Aufruf ruft `interactive_rip` einmalig
|
||||
`merge_album()` auf und schreibt album.json.
|
||||
|
||||
---
|
||||
|
||||
## Wiederholbares Apply (Re-Apply in-place)
|
||||
|
||||
### Ziel
|
||||
|
||||
`apply` soll beliebig oft wiederholbar sein — auch nachträglich im
|
||||
Jellyfin-Zielverzeichnis. Der User editiert album.json und ruft apply
|
||||
erneut auf; Dateinamen, Tags und Playlist werden aktualisiert.
|
||||
|
||||
### Invariante: album.json bleibt immer erhalten
|
||||
|
||||
`apply` berührt album.json nie. Sie ist die einzige persistente
|
||||
Wahrheitsquelle für alle Metadaten. Selbst wenn Tags oder Dateinamen
|
||||
abweichen, definiert album.json den Sollzustand.
|
||||
|
||||
### Stabilität durch Tracknummer-Präfix
|
||||
|
||||
Der stabile Anker beim Re-Apply ist die führende Tracknummer im
|
||||
Dateinamen:
|
||||
|
||||
```
|
||||
01_-_Alter_Titel.flac → nach Edit → 01_-_Neuer_Titel.flac
|
||||
```
|
||||
|
||||
`discover_audio_files()` identifiziert Tracks bereits nach dem
|
||||
numerischen Präfix (unabhängig vom Titelanteil). Re-Apply ist damit
|
||||
robust gegenüber beliebigen Titeländerungen.
|
||||
|
||||
### Was apply bei jedem Aufruf tut (idempotent)
|
||||
|
||||
1. Audiodateien per Tracknummer-Präfix identifizieren
|
||||
2. Umbenennen gemäß aktuellem album.json (in-place)
|
||||
3. Alle Audio-Tags neu schreiben (überschreiben)
|
||||
4. Cover neu einbetten (überschreiben)
|
||||
5. Playlist neu generieren (überschreiben, gleicher Dateiname)
|
||||
6. album.json unangetastet lassen
|
||||
|
||||
### Verzeichnisumbenennung bei Albumname-Änderung
|
||||
|
||||
Wenn sich `album` oder `year` in album.json ändern, ändert sich der
|
||||
korrekte Verzeichnisname. Im Jellyfin-Ordner ist das heikel (Jellyfin
|
||||
erkennt das Album ggf. als neu).
|
||||
|
||||
Vorschlag: Verzeichnisumbenennung nur mit explizitem Flag:
|
||||
```
|
||||
musiksammlung apply --in-place --rename-dir <album_dir>
|
||||
```
|
||||
Ohne Flag: Dateien und Tags werden aktualisiert, Verzeichnisname bleibt.
|
||||
|
||||
---
|
||||
|
||||
## Cleanup nach dem Ripping
|
||||
|
||||
abcde hinterlässt Arbeitsverzeichnisse unterhalb der CDn-Ordner:
|
||||
|
||||
```
|
||||
Album/
|
||||
CD1/
|
||||
abcde.XXXXX/ ← Temp-Verzeichnis von abcde
|
||||
track01.wav ← evtl. noch vorhandene WAV-Zwischendateien
|
||||
status
|
||||
mbid.1
|
||||
```
|
||||
|
||||
### Wann aufräumen
|
||||
|
||||
**Automatisch am Ende von Phase B** (nach erfolgreichem Ripping):
|
||||
|
||||
```python
|
||||
for abcde_dir in cd_dir.glob("abcde.*"):
|
||||
shutil.rmtree(abcde_dir)
|
||||
```
|
||||
|
||||
Alternativ als expliziter Befehl für manuelles Aufräumen:
|
||||
```
|
||||
musiksammlung cleanup <album_dir>
|
||||
```
|
||||
|
||||
Beide Varianten sollten implementiert werden: automatisch als Default,
|
||||
manuell als Fallback wenn Phase B mit Fehler abgebrochen wurde.
|
||||
|
||||
---
|
||||
|
||||
## Neuer CLI-Befehl: gen_json
|
||||
|
||||
### Zweck
|
||||
|
||||
Rekonstruiert album.json aus dem vorhandenen Dateibaum, wenn die Datei
|
||||
versehentlich gelöscht wurde. Kann auch für Alben genutzt werden, die
|
||||
mit anderen Tools gerippt wurden.
|
||||
|
||||
```
|
||||
musiksammlung gen_json <album_dir>
|
||||
```
|
||||
|
||||
### Namenskonvention (verbindlich festgelegt)
|
||||
|
||||
**Album-Verzeichnis:**
|
||||
```
|
||||
Sanitized_Artist_-_Sanitized_Album_Title_(YYYY)/
|
||||
Sanitized_Album_Title_(YYYY)/ ← wenn Artist "Various Artists"
|
||||
```
|
||||
|
||||
Beispiele:
|
||||
```
|
||||
Pink_Floyd_-_The_Wall_(1979)/
|
||||
Bach_-_Brandenburg_Concertos_(1967)/
|
||||
Various_Artists_-_Now_Thats_What_I_Call_Music_(2001)/
|
||||
```
|
||||
|
||||
**CDn-Unterverzeichnis** (bei Multi-Disc):
|
||||
```
|
||||
CD1/ CD2/ ...
|
||||
```
|
||||
Bei Single-Disc: Audiodateien liegen direkt im Album-Verzeichnis oder
|
||||
in `CD1/` — beides wird akzeptiert.
|
||||
|
||||
**Track-Dateiname:**
|
||||
```
|
||||
NN_-_Sanitized_Track_Title.flac
|
||||
NN_-_Sanitized_Track_Title_-_Sanitized_Track_Artist.flac
|
||||
```
|
||||
|
||||
`NN` ist zweistellig mit führender Null (`01`, `02`, ..., `99`).
|
||||
`_-_` (Unterstrich-Bindestrich-Unterstrich) ist der strukturelle
|
||||
Trenner — kein einfacher `-` innerhalb eines Feldes ist `_-_`.
|
||||
|
||||
### gen_json Algorithmus
|
||||
|
||||
```
|
||||
1. Verzeichnisname parsen:
|
||||
"Pink_Floyd_-_The_Wall_(1979)" →
|
||||
artist = "Pink Floyd" (vor erstem _-_)
|
||||
album = "The Wall" (zwischen _-_ und _(YYYY))
|
||||
year = 1979 (aus _(YYYY))
|
||||
|
||||
2. CDn-Unterverzeichnisse → disc_number (Zahl aus "CD1", "CD2" etc.)
|
||||
Keine CDn-Dirs → Single-Disc, disc_number = 1
|
||||
|
||||
3. Pro Disc: Audiodateien nach Tracknummer-Präfix sortieren:
|
||||
"01_-_In_the_Flesh.flac" → track_number=1, title="In the Flesh"
|
||||
"02_-_The_Thin_Ice_-_Roger_Waters.flac"
|
||||
→ track_number=2, title="The Thin Ice",
|
||||
artist="Roger Waters"
|
||||
|
||||
4. Audio-Tags lesen (mutagen) — höhere Priorität als Dateiname:
|
||||
- title, artist: aus Tags übernehmen wenn vorhanden
|
||||
(Tags enthalten Original-Strings ohne Sanitizing)
|
||||
- duration_ms: aus Audiodatei (exakt, besser als MB oder TOC)
|
||||
- genre: nur aus Tags verfügbar, nirgends im Dateinamen kodiert
|
||||
|
||||
5. album.json schreiben (fehlende Felder als null)
|
||||
```
|
||||
|
||||
### Daten-Rangfolge in gen_json
|
||||
|
||||
| Feld | Quelle 1 (bevorzugt) | Quelle 2 (Fallback) |
|
||||
|------|---------------------|---------------------|
|
||||
| title | Audio-Tag | Dateiname (desanitized) |
|
||||
| artist | Audio-Tag | Dateiname / Verzeichnis |
|
||||
| album | Audio-Tag | Verzeichnisname |
|
||||
| year | Audio-Tag | Verzeichnisname _(YYYY) |
|
||||
| genre | Audio-Tag | — (bleibt null) |
|
||||
| duration_ms | Audiodatei (mutagen) | — |
|
||||
| disc_number | CDn-Verzeichnis | — |
|
||||
| track_number | Dateiname-Präfix | Audio-Tag |
|
||||
|
||||
### Was gen_json nicht rekonstruieren kann
|
||||
|
||||
- `disc.disc_id` (physischer TOC-Fingerprint — nicht in Dateien)
|
||||
- `disc.name` (z.B. "Live in Berlin" — nicht im Dateinamen kodiert)
|
||||
- `genre` wenn Audio-Tags fehlen
|
||||
|
||||
### Klassik: Komponist vs. Interpret
|
||||
|
||||
Beide Felder werden in den Audio-Tags gespeichert (COMPOSER-Tag bei
|
||||
FLAC/MP3). `gen_json` liest COMPOSER aus den Tags und kann Komponist
|
||||
von Interpret trennen — ohne spezielle Namenskonvention im Dateinamen.
|
||||
|
||||
Der Dateinamen-Titel enthält bei Klassik typischerweise Werk + Satz:
|
||||
```
|
||||
01_-_Symphony_No_5_Op_67_I_Allegro_con_brio.flac
|
||||
```
|
||||
Komponist steht im Verzeichnisnamen (`Bach_-_...`) und im COMPOSER-Tag.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue