CDDB→album.json + LLM-Prompts mit Track-Künstler
ripper: nach erfolgreichem CDDB-Rip album.json im Album-Verzeichnis speichern (Artist, Titel, alle Discs mit Track-Künstlern) — Workflow- Lücke zwischen rip und apply geschlossen. llm_parser, vision_llm: Prompts erklären das optionale Track-artist- Feld; LLM setzt es nur wenn Track-Interpret vom Album-Künstler abweicht. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
255496bd1b
commit
bafea5f335
3 changed files with 40 additions and 8 deletions
|
|
@ -17,20 +17,23 @@ SYSTEM_PROMPT = """\
|
|||
Du bist ein Parser für CD-Tracklisten. Extrahiere die Metadaten als JSON.
|
||||
|
||||
REGELN:
|
||||
- "artist": Wenn verschiedene Interpreten pro Track → "Various Artists". \
|
||||
NUR wenn alle Tracks denselben Interpreten haben, nimm diesen als artist.
|
||||
- "artist" (Album-Ebene): Hauptinterpret. Bei Samplern/Compilations → "Various Artists".
|
||||
- "album": Der Albumtitel (z.B. "Deutsche Volkslieder").
|
||||
- "year": NUR wenn ein Jahr explizit im Text steht. Sonst null. NICHTS ERFINDEN.
|
||||
- "title": NUR der Songtitel. KEINE Komponisten, KEINE Interpreten, KEINE Zeitangaben.
|
||||
- "title": NUR der Songtitel. KEINE Komponisten, KEINE Zeitangaben.
|
||||
Beispiel: "Wer recht in Freuden wandern will" — NICHT \
|
||||
"Wer recht in Freuden wandern will (Klauer – Geibel)"
|
||||
- "artist" (Track-Ebene, optional): NUR setzen wenn der Track-Interpret vom Album-Künstler \
|
||||
abweicht (z.B. bei Samplern oder Klassik mit verschiedenen Solisten/Dirigenten). \
|
||||
Ist der Interpret überall gleich, dieses Feld weglassen.
|
||||
- Jede Tracknummer darf nur EINMAL vorkommen. Keine Duplikate.
|
||||
- "CD 1", "CD 2", "Disc 1" etc. → eigene disc_number. Sonst disc_number=1.
|
||||
|
||||
Gib ausschließlich valides JSON zurück:
|
||||
{"artist":"Various Artists","album":"Albumname","year":null,\
|
||||
"discs":[{"disc_number":1,"name":null,\
|
||||
"tracks":[{"track_number":1,"title":"Nur der Songtitel"}]}]}
|
||||
"tracks":[{"track_number":1,"title":"Songtitel","artist":"Interpret A"},\
|
||||
{"track_number":2,"title":"Songtitel","artist":"Interpret B"}]}]}
|
||||
|
||||
/no_think"""
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ from typing import NamedTuple
|
|||
from pydantic import BaseModel
|
||||
|
||||
from musiksammlung.config import AudioFormat
|
||||
from musiksammlung.models import Album as AlbumModel
|
||||
from musiksammlung.models import Disc as DiscModel
|
||||
from musiksammlung.models import Track as TrackModel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -433,6 +436,7 @@ def interactive_rip(config: RipperConfig) -> None:
|
|||
album_name = f"Album{album_counter}"
|
||||
|
||||
disc_counter = 1
|
||||
all_discs: list[DiscModel] = []
|
||||
|
||||
while True:
|
||||
print(f"\n Album: {album_name}")
|
||||
|
|
@ -466,6 +470,17 @@ def interactive_rip(config: RipperConfig) -> None:
|
|||
print(f" ✓ Done — {len(tracks)} tracks")
|
||||
for t in tracks:
|
||||
print(f" {t.track_number:2d}. {t.title} [{t.artist}]")
|
||||
all_discs.append(DiscModel(
|
||||
disc_number=disc_num,
|
||||
tracks=[
|
||||
TrackModel(
|
||||
track_number=t.track_number,
|
||||
title=t.title,
|
||||
artist=t.artist,
|
||||
)
|
||||
for t in tracks
|
||||
],
|
||||
))
|
||||
else:
|
||||
print(" ✓ Done (no CDDB data)")
|
||||
|
||||
|
|
@ -483,6 +498,17 @@ def interactive_rip(config: RipperConfig) -> None:
|
|||
|
||||
disc_counter += 1
|
||||
|
||||
if all_discs:
|
||||
artist = all_discs[0].tracks[0].artist or album_name
|
||||
album_model = AlbumModel(artist=artist, album=album_name, discs=all_discs)
|
||||
album_root = config.output_dir / _sanitize_name(album_name)
|
||||
json_path = album_root / "album.json"
|
||||
json_path.write_text(
|
||||
album_model.model_dump_json(indent=2), encoding="utf-8"
|
||||
)
|
||||
print(f"\n album.json gespeichert: {json_path}")
|
||||
print(" → Weiter mit: musiksammlung apply <album-verzeichnis> album.json")
|
||||
|
||||
raw_album = input("\nNext album? (y/n): ")
|
||||
if _clean_input(raw_album).lower() != "y":
|
||||
break
|
||||
|
|
|
|||
|
|
@ -20,14 +20,17 @@ Lies das Foto einer CD-Rückseite oder eines Booklets ab. Das Bild kann gedreht
|
|||
Extrahiere daraus die Metadaten und die vollständige Trackliste.
|
||||
|
||||
WICHTIG:
|
||||
- "artist" ist der Hauptinterpret oder "Various Artists" bei Samplern/Compilations.
|
||||
- "artist" (Album-Ebene): Hauptinterpret oder "Various Artists" bei Samplern/Compilations.
|
||||
- "album" ist der Albumtitel (z.B. "Deutsche Volkslieder", "Abbey Road").
|
||||
- "year" ist das Erscheinungsjahr (Zahl oder null wenn nicht sichtbar).
|
||||
- Lies die Tracktitel GENAU so ab, wie sie auf der CD stehen.
|
||||
- Achte besonders auf korrekte deutsche Umlaute (ä, ö, ü, ß).
|
||||
- Lasse Zeitangaben (z.B. "3:12") aus dem Titel weg.
|
||||
- "artist" (Track-Ebene, optional): NUR setzen wenn der Interpret dieses Tracks vom \
|
||||
Album-Künstler abweicht (z.B. bei Samplern oder Klassik mit verschiedenen Solisten). \
|
||||
Ist der Interpret überall gleich, dieses Feld weglassen.
|
||||
- Wenn "CD 1", "CD 2", "Disc 1" etc. sichtbar sind, erstelle mehrere Einträge in "discs".
|
||||
- Ohne Disc-Angabe: eine Disc mit disc_number=1.
|
||||
- Lasse Zeitangaben (z.B. "3:12") und Interpretenangaben pro Track weg.
|
||||
- MEHRSPALTIGE LAYOUTS: CD-Rückseiten haben oft 2, 3 oder 4 Spalten nebeneinander.
|
||||
Lies ALLE Spalten vollständig von oben nach unten, bevor du zur nächsten Spalte gehst.
|
||||
Überspringen oder Auslassen von Spalten ist ein häufiger Fehler — lies jede Spalte komplett.
|
||||
|
|
@ -36,8 +39,8 @@ Antworte NUR mit dem JSON, ohne Erklärung. Beispiel:
|
|||
|
||||
{"artist":"Various Artists","album":"Deutsche Volkslieder","year":null,""" # noqa: E501
|
||||
VISION_PROMPT += """"discs":[{"disc_number":1,"name":null,"tracks":["""
|
||||
VISION_PROMPT += """{"track_number":1,"title":"Erster Song"},"""
|
||||
VISION_PROMPT += """{"track_number":2,"title":"Zweiter Song"}]}]}"""
|
||||
VISION_PROMPT += """{"track_number":1,"title":"Erster Song","artist":"Interpret A"},"""
|
||||
VISION_PROMPT += """{"track_number":2,"title":"Zweiter Song","artist":"Interpret B"}]}]}"""
|
||||
VISION_PROMPT += """
|
||||
|
||||
Jetzt lies das Bild ab und gib das vollständige JSON aus. /no_think"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue