133 lines
3.8 KiB
Python
133 lines
3.8 KiB
Python
"""
|
||
fcco-Converter V2 – Metadaten-Modul
|
||
|
||
Hilfsfunktionen für ID3-Tags, Cover-Bilder und Albumname-Generierung.
|
||
"""
|
||
|
||
import re
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
|
||
from mutagen.easyid3 import EasyID3
|
||
from mutagen.id3 import ID3, APIC
|
||
|
||
from .config import WEEKDAY_SHORT_DE
|
||
|
||
|
||
def generate_album_name(veranstaltung: str = "") -> str:
|
||
"""Erstellt einen Albumnamen basierend auf dem aktuellen Datum und der Veranstaltung."""
|
||
date_str = datetime.now().strftime("%d.%m.%Y")
|
||
if veranstaltung:
|
||
return f"{date_str} {veranstaltung}"
|
||
return date_str
|
||
|
||
|
||
def generate_folder_name(date_part: str, veranstaltung: str) -> str:
|
||
"""Erstellt den Ordnernamen für den Export."""
|
||
if veranstaltung:
|
||
return f"{date_part} {veranstaltung}"
|
||
return date_part
|
||
|
||
|
||
def generate_date_part() -> str:
|
||
"""Erstellt das Datumskürzel (z.B. '260719Sa') für die aktuelle Zeit."""
|
||
now = datetime.now()
|
||
return now.strftime("%y%m%d") + WEEKDAY_SHORT_DE[now.weekday()]
|
||
|
||
|
||
def extract_event_from_folder(file_path: Path) -> tuple[str, str]:
|
||
"""Versucht, Datum und Veranstaltung aus dem Ordnernamen zu extrahieren.
|
||
|
||
Erwartetes Format: 'YYMMDDWt Veranstaltungsname'
|
||
z.B. '260406Mo Ostermontag'
|
||
|
||
Returns:
|
||
(date_part, veranstaltung) oder ("", "") wenn nicht erkannt.
|
||
"""
|
||
folder_name = file_path.parent.name
|
||
if len(folder_name) >= 8 and folder_name[:6].isdigit() and folder_name[6:8] in WEEKDAY_SHORT_DE:
|
||
date_part = folder_name[:8]
|
||
veranstaltung = folder_name[8:].strip() if len(folder_name) > 8 else ""
|
||
return date_part, veranstaltung
|
||
return "", ""
|
||
|
||
|
||
def extract_title_from_filename(filename: str) -> str:
|
||
"""Extrahiert einen sauberen Titel aus dem komplexen Dateinamen-Format.
|
||
|
||
Format-Erwartung: [Prefix]_[Track]_[Type]_[Lang][ Remainder]
|
||
Beispiele:
|
||
260719So_N_10_Predigt_D Vorname Nachname -> "Predigt Vorname Nachname"
|
||
260719So_N_04_Lied_D Zum blauen Himmel -> "Zum blauen Himmel"
|
||
"""
|
||
# Regulärer Ausdruck, um die Komponenten zu extrahieren
|
||
match = re.match(r"^.*?_\d+_(?P<type>[a-zA-Z]+)_(?P<lang>[a-zA-Z]+)(?: (?P<remainder>.*))?$", filename)
|
||
if not match:
|
||
return filename
|
||
|
||
typ = match.group("type")
|
||
lang = match.group("lang")
|
||
remainder = match.group("remainder") or ""
|
||
|
||
typ_lower = typ.lower()
|
||
|
||
if typ_lower in ["predigt", "vorwort", "gedicht"]:
|
||
if remainder:
|
||
return f"{typ} {remainder}"
|
||
return f"{typ} {lang}"
|
||
|
||
elif typ_lower == "lied":
|
||
if remainder:
|
||
return remainder
|
||
return f"{typ} {lang}"
|
||
|
||
elif typ_lower in ["chor", "orchester"]:
|
||
if remainder:
|
||
return f"{remainder} ({typ})"
|
||
return f"{typ} {lang}"
|
||
|
||
else:
|
||
# Fallback
|
||
if remainder:
|
||
return f"{typ} {remainder}"
|
||
return f"{typ} {lang}"
|
||
|
||
|
||
from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB, TRCK, TDRC
|
||
|
||
def apply_id3_tags(
|
||
mp3_path: Path,
|
||
title: str,
|
||
artist: str,
|
||
album: str,
|
||
track_number: int,
|
||
year: str,
|
||
cover_data: bytes | None = None,
|
||
cover_mime: str = "image/jpeg",
|
||
) -> None:
|
||
"""Schreibt ID3-Metadaten und optional ein Cover in die MP3-Datei."""
|
||
try:
|
||
tags = ID3(str(mp3_path))
|
||
except Exception:
|
||
tags = ID3()
|
||
|
||
tags.add(TIT2(encoding=3, text=title))
|
||
tags.add(TPE1(encoding=3, text=artist or "Unbekannt"))
|
||
tags.add(TALB(encoding=3, text=album or "Unbekanntes Album"))
|
||
tags.add(TRCK(encoding=3, text=str(track_number)))
|
||
if year:
|
||
tags.add(TDRC(encoding=3, text=year))
|
||
|
||
if cover_data:
|
||
tags.add(
|
||
APIC(
|
||
encoding=3,
|
||
mime=cover_mime,
|
||
type=3,
|
||
desc="Cover",
|
||
data=cover_data,
|
||
)
|
||
)
|
||
|
||
tags.save(str(mp3_path), v2_version=3)
|