From 2b564a6dd34946fc3cb0c1e283ffa09396ec4f35 Mon Sep 17 00:00:00 2001 From: Manuel Weiser Date: Thu, 3 Jul 2025 10:49:36 +0200 Subject: [PATCH] =?UTF-8?q?F=C3=BCge=20Unterst=C3=BCtzung=20f=C3=BCr=20die?= =?UTF-8?q?=20Erstellung=20von=20Tracklisten=20hinzu=20und=20verbessere=20?= =?UTF-8?q?Duplikat-Filterung=20in=20Audacity-Labels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 ++ README.md | 41 ++++++++++++++++++++++++++++++++--------- cue2auda.py | 48 ++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d65d45d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.cue +*.txt diff --git a/README.md b/README.md index 31576a3..f2a2fc7 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,21 @@ # CUE to Audacity Label Converter -Ein Python-Script, das CUE-Dateien (von rekordbox DJ oder anderen Quellen) in Audacity-Label-Dateien umwandelt. +Ein Python-Script, das CUE-Dateien (von rekordbox DJ oder anderen Quellen) in Audacity-Label-Dateien und schöne Tracklists umwandelt. ## Beschreibung -Dieses Tool liest CUE-Dateien und erstellt daraus Textdateien mit Zeitstempeln und Track-Titeln, die direkt in Audacity als Label-Track importiert werden können. Besonders nützlich für DJ-Sets oder lange Audio-Aufnahmen, die in einzelne Tracks unterteilt werden sollen. +Dieses Tool liest CUE-Dateien und erstellt daraus zwei Ausgabe-Dateien: +1. **Audacity-Labels**: Textdateien mit Zeitstempeln für den Import in Audacity +2. **Tracklist**: Professionell formatierte Trackliste zum Teilen + +Besonders nützlich für DJ-Sets oder lange Audio-Aufnahmen, die in einzelne Tracks unterteilt werden sollen. ## Features - Unterstützt rekordbox CUE-Dateien im HH:MM:SS Format - Automatische Erkennung von Standard CUE-Formaten (MM:SS:FF mit CD-Frames) +- **Intelligente Duplikat-Filterung**: Entfernt Tracks, die innerhalb der letzten 2 Tracks bereits vorkamen +- **Zwei Ausgabe-Formate**: Audacity-Labels und professionelle Tracklist - Flexible Regex-Pattern für verschiedene Einrückungen (Tabs/Leerzeichen) - UTF-8 Encoding für internationale Zeichen - Plattformübergreifend (Windows, macOS, Linux) @@ -57,6 +63,12 @@ TRACK 01 AUDIO 150.000000 150.000000 Song Title ``` +### Ausgabe (Tracklist-Datei) +``` +01. Artist Name - Song Title (02:30) +02. Another Artist - Another Song (05:15) +``` + ## Unterstützte CUE-Formate 1. **rekordbox Format**: `HH:MM:SS` (Stunden:Minuten:Sekunden) @@ -68,21 +80,32 @@ Das Script erkennt automatisch das Format basierend auf den Zeitwerten. 1. Öffnen Sie Ihre Audio-Datei in Audacity 2. Gehen Sie zu `Datei` → `Importieren` → `Labels...` -3. Wählen Sie die generierte `.txt` Datei aus +3. Wählen Sie die generierte `*_audacity.txt` Datei aus 4. Die Zeitmarken erscheinen als Label-Track -## Dateien +## Ausgabedateien -- `cue2auda.py` - Hauptscript -- `requirements.txt` - Python-Abhängigkeiten (leer, da nur Standard-Bibliotheken verwendet werden) -- `README.md` - Diese Datei +Das Script erstellt automatisch zwei Dateien: + +- `filename_audacity.txt` - Audacity-Label-Datei für den Import +- `filename_tracklist.txt` - Professionelle Tracklist zum Teilen ## Beispiel-Workflow 1. Exportieren Sie ein DJ-Set aus rekordbox mit CUE-Datei 2. Führen Sie das Script aus: `python cue2auda.py /pfad/zu/cue/dateien` -3. Importieren Sie die generierte `.txt` Datei in Audacity -4. Nutzen Sie die Labels zum Schneiden oder Navigieren +3. **Zwei Dateien werden erstellt:** + - `filename_audacity.txt` → Importieren Sie diese in Audacity als Labels + - `filename_tracklist.txt` → Teilen Sie diese schöne Tracklist +4. Nutzen Sie die Labels zum Schneiden oder Navigieren in Audacity + +## Duplikat-Filterung + +Das Script erkennt automatisch Duplikate in DJ-Mixes und filtert Tracks heraus, die innerhalb der letzten 2 Tracks bereits vorkamen. Dies ist besonders nützlich bei: + +- **Blend-Übergängen**: Wenn Tracks überlappend gespielt werden +- **Loop-Rolls**: Wenn derselbe Track kurz wiederholt wird +- **DJ-Techniken**: Drop-outs, Cuts und Re-Entries ## Technische Details diff --git a/cue2auda.py b/cue2auda.py index 4c9f87d..46fd422 100644 --- a/cue2auda.py +++ b/cue2auda.py @@ -23,13 +23,19 @@ for cueFileName in glob.glob(os.path.join(thePath, "*.cue")): #print(cueFileContent) # Create label file - labelFileName = os.path.splitext(cueFileName)[0] + ".txt" - with open(labelFileName, "w", encoding="utf-8") as labelFile: + labelFileName = os.path.splitext(cueFileName)[0] + "_audacity.txt" + tracklistFileName = os.path.splitext(cueFileName)[0] + "_tracklist.txt" + + with open(labelFileName, "w", encoding="utf-8") as labelFile, \ + open(tracklistFileName, "w", encoding="utf-8") as tracklistFile: #print ("###" + labelFileName + "###") # Process file theTitle = "" # initialize title now in order to keep it available when scanning subsequent INDEX line + thePerformer = "" # initialize performer trackCount = 0 + lastTitles = [] # Track the last few titles to avoid duplicates within a few tracks + maxTrackDistance = 2 # Filter duplicates within this many tracks for lineNum, line in enumerate(cueFileContent, 1): originalLine = line @@ -40,6 +46,11 @@ for cueFileName in glob.glob(os.path.join(thePath, "*.cue")): if theMatchTitle is not None: theTitle = theMatchTitle.group(1) + # Match PERFORMER - try multiple patterns for different indentation (tabs or spaces) + theMatchPerformer = re.search(r'PERFORMER\s+"([^"]+)"', line) + if theMatchPerformer is not None: + thePerformer = theMatchPerformer.group(1) + # Match INDEX 01 - try multiple patterns for different formats (tabs or spaces) theMatchIndex = re.search(r'INDEX\s+01\s+(\d{1,2}):(\d{2}):(\d{2})', line) if theMatchIndex is not None: @@ -47,18 +58,39 @@ for cueFileName in glob.glob(os.path.join(thePath, "*.cue")): theMinutes = int(theMatchIndex.group(2)) # Minutes theSeconds = int(theMatchIndex.group(3)) # Seconds - trackCount += 1 - # Convert HH:MM:SS to total seconds theStartTime = (theHours * 3600) + (theMinutes * 60) + theSeconds - # format theStartTime - theStartTime = "{:.6f}".format(theStartTime) + # Check for duplicates: skip if same title appears within the last few tracks + isDuplicate = theTitle in lastTitles[-maxTrackDistance:] - # Write time and title to label file - labelFile.write(theStartTime + "\t" + theStartTime + "\t" + theTitle + "\n") + if not isDuplicate: + trackCount += 1 + + # format theStartTime + theStartTimeFormatted = "{:.6f}".format(theStartTime) + + # Format time for tracklist (MM:SS) + timeMinutes = theStartTime // 60 + timeSeconds = theStartTime % 60 + timeFormatted = f"{int(timeMinutes):02d}:{int(timeSeconds):02d}" + + # Write time and title to Audacity label file + labelFile.write(theStartTimeFormatted + "\t" + theStartTimeFormatted + "\t" + theTitle + "\n") + + # Write to tracklist file: TrackNr. Artist - Track (Time) + if thePerformer: + tracklistFile.write(f"{trackCount:02d}. {thePerformer} - {theTitle} ({timeFormatted})\n") + else: + tracklistFile.write(f"{trackCount:02d}. {theTitle} ({timeFormatted})\n") + + # Add to title history + lastTitles.append(theTitle) + else: + print(f"Skipping duplicate: '{theTitle}' at {theHours:02d}:{theMinutes:02d}:{theSeconds:02d} (appeared within last {maxTrackDistance} tracks)") print(f"Created {trackCount} labels in {labelFileName}") + print(f"Created tracklist in {tracklistFileName}") # end for line in cueFileContent