Füge Unterstützung für die Erstellung von Tracklisten hinzu und verbessere Duplikat-Filterung in Audacity-Labels
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.cue
|
||||||
|
*.txt
|
41
README.md
41
README.md
@ -1,15 +1,21 @@
|
|||||||
# CUE to Audacity Label Converter
|
# 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
|
## 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
|
## Features
|
||||||
|
|
||||||
- Unterstützt rekordbox CUE-Dateien im HH:MM:SS Format
|
- Unterstützt rekordbox CUE-Dateien im HH:MM:SS Format
|
||||||
- Automatische Erkennung von Standard CUE-Formaten (MM:SS:FF mit CD-Frames)
|
- 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)
|
- Flexible Regex-Pattern für verschiedene Einrückungen (Tabs/Leerzeichen)
|
||||||
- UTF-8 Encoding für internationale Zeichen
|
- UTF-8 Encoding für internationale Zeichen
|
||||||
- Plattformübergreifend (Windows, macOS, Linux)
|
- Plattformübergreifend (Windows, macOS, Linux)
|
||||||
@ -57,6 +63,12 @@ TRACK 01 AUDIO
|
|||||||
150.000000 150.000000 Song Title
|
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
|
## Unterstützte CUE-Formate
|
||||||
|
|
||||||
1. **rekordbox Format**: `HH:MM:SS` (Stunden:Minuten:Sekunden)
|
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
|
1. Öffnen Sie Ihre Audio-Datei in Audacity
|
||||||
2. Gehen Sie zu `Datei` → `Importieren` → `Labels...`
|
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
|
4. Die Zeitmarken erscheinen als Label-Track
|
||||||
|
|
||||||
## Dateien
|
## Ausgabedateien
|
||||||
|
|
||||||
- `cue2auda.py` - Hauptscript
|
Das Script erstellt automatisch zwei Dateien:
|
||||||
- `requirements.txt` - Python-Abhängigkeiten (leer, da nur Standard-Bibliotheken verwendet werden)
|
|
||||||
- `README.md` - Diese Datei
|
- `filename_audacity.txt` - Audacity-Label-Datei für den Import
|
||||||
|
- `filename_tracklist.txt` - Professionelle Tracklist zum Teilen
|
||||||
|
|
||||||
## Beispiel-Workflow
|
## Beispiel-Workflow
|
||||||
|
|
||||||
1. Exportieren Sie ein DJ-Set aus rekordbox mit CUE-Datei
|
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`
|
2. Führen Sie das Script aus: `python cue2auda.py /pfad/zu/cue/dateien`
|
||||||
3. Importieren Sie die generierte `.txt` Datei in Audacity
|
3. **Zwei Dateien werden erstellt:**
|
||||||
4. Nutzen Sie die Labels zum Schneiden oder Navigieren
|
- `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
|
## Technische Details
|
||||||
|
|
||||||
|
48
cue2auda.py
48
cue2auda.py
@ -23,13 +23,19 @@ for cueFileName in glob.glob(os.path.join(thePath, "*.cue")):
|
|||||||
#print(cueFileContent)
|
#print(cueFileContent)
|
||||||
|
|
||||||
# Create label file
|
# Create label file
|
||||||
labelFileName = os.path.splitext(cueFileName)[0] + ".txt"
|
labelFileName = os.path.splitext(cueFileName)[0] + "_audacity.txt"
|
||||||
with open(labelFileName, "w", encoding="utf-8") as labelFile:
|
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 + "###")
|
#print ("###" + labelFileName + "###")
|
||||||
|
|
||||||
# Process file
|
# Process file
|
||||||
theTitle = "" # initialize title now in order to keep it available when scanning subsequent INDEX line
|
theTitle = "" # initialize title now in order to keep it available when scanning subsequent INDEX line
|
||||||
|
thePerformer = "" # initialize performer
|
||||||
trackCount = 0
|
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):
|
for lineNum, line in enumerate(cueFileContent, 1):
|
||||||
originalLine = line
|
originalLine = line
|
||||||
@ -40,6 +46,11 @@ for cueFileName in glob.glob(os.path.join(thePath, "*.cue")):
|
|||||||
if theMatchTitle is not None:
|
if theMatchTitle is not None:
|
||||||
theTitle = theMatchTitle.group(1)
|
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)
|
# 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)
|
theMatchIndex = re.search(r'INDEX\s+01\s+(\d{1,2}):(\d{2}):(\d{2})', line)
|
||||||
if theMatchIndex is not None:
|
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
|
theMinutes = int(theMatchIndex.group(2)) # Minutes
|
||||||
theSeconds = int(theMatchIndex.group(3)) # Seconds
|
theSeconds = int(theMatchIndex.group(3)) # Seconds
|
||||||
|
|
||||||
trackCount += 1
|
|
||||||
|
|
||||||
# Convert HH:MM:SS to total seconds
|
# Convert HH:MM:SS to total seconds
|
||||||
theStartTime = (theHours * 3600) + (theMinutes * 60) + theSeconds
|
theStartTime = (theHours * 3600) + (theMinutes * 60) + theSeconds
|
||||||
|
|
||||||
# format theStartTime
|
# Check for duplicates: skip if same title appears within the last few tracks
|
||||||
theStartTime = "{:.6f}".format(theStartTime)
|
isDuplicate = theTitle in lastTitles[-maxTrackDistance:]
|
||||||
|
|
||||||
# Write time and title to label file
|
if not isDuplicate:
|
||||||
labelFile.write(theStartTime + "\t" + theStartTime + "\t" + theTitle + "\n")
|
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 {trackCount} labels in {labelFileName}")
|
||||||
|
print(f"Created tracklist in {tracklistFileName}")
|
||||||
|
|
||||||
# end for line in cueFileContent
|
# end for line in cueFileContent
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user