2 Commits
Author SHA1 Message Date
joel c486339f8d feat: smart title extraction from filename for 2.0.2 2026-07-20 18:29:58 +02:00
joel 87b5ba91b1 Rename ZIP output to macos instead of darwin 2026-07-20 18:18:47 +02:00
6 changed files with 73 additions and 51 deletions
+25 -47
View File
@@ -1,6 +1,6 @@
# fcco Converter V2 # fcco Converter V2
WAV-zu-MP3-Konverter mit grafischer Benutzeroberfläche. Unterstützt automatische Metadaten-Erstellung (Künstler, Album, Titel, Tracknummer), Cover-Bilder und alphabetische Sortierung. Läuft auf **Windows** und **macOS**. WAV-zu-MP3-Konverter mit grafischer Benutzeroberfläche. Unterstützt automatische Metadaten-Erstellung (Künstler, Album, Titel, Tracknummer), Cover-Bilder und alphabetische Sortierung. Läuft auf Windows und macOS.
--- ---
@@ -13,16 +13,33 @@ WAV-zu-MP3-Konverter mit grafischer Benutzeroberfläche. Unterstützt automatisc
- Einstellungen werden dauerhaft gespeichert - Einstellungen werden dauerhaft gespeichert
- Fortschrittsanzeige pro Datei und gesamt - Fortschrittsanzeige pro Datei und gesamt
- Automatisches Update direkt aus der App - Automatisches Update direkt aus der App
- Moderne, dunkle Benutzeroberfläche (CustomTkinter) - Moderne, dunkle Benutzeroberfläche
---
## Automatische Titel-Extrahierung (Neu in V2.0.2)
Das Programm erkennt Dateinamen im typischen fcco-Format und erstellt daraus automatisch saubere Songtitel (ID3-Tags).
Das Muster wird nach dem Unterstrich-Format extrahiert. Hier sind Beispiele, wie aus Dateinamen automatisch MP3-Titel gebildet werden:
- 260719So_N_10_Predigt_D Vorname Nachname.wav -> "Predigt Vorname Nachname"
- 260719So_N_07_Vorwort_D Vorname Nachname.wav -> "Vorwort Vorname Nachname"
- 260719So_N_09_Gedicht_D Vorname Nachname.wav -> "Gedicht Vorname Nachname"
- 260719So_N_10_Predigt_D.wav -> "Predigt D"
- 260719So_N_10_Predigt_D Gast.wav -> "Predigt Gast"
- 260719So_N_06_Lied_R О пройденном я подвожу итог.wav -> "О пройденном я подвожу итог"
- 260719So_N_04_Lied_D Zum blauen Himmel.wav -> "Zum blauen Himmel"
- 260719So_N_04_Chor_D Zum blauen Himmel.wav -> "Zum blauen Himmel (Chor)"
- 260719So_N_04_Orchester_D Zum blauen Himmel.wav -> "Zum blauen Himmel (Orchester)"
--- ---
## Installation (Endnutzer) ## Installation (Endnutzer)
Lade die neueste Version von der [Releases-Seite](https://git.joelunger.de/public/fcco-Converter/releases) herunter: Lade die neueste Version von der Releases-Seite (Gitea) herunter:
- **Windows**: `fcco-Converter-windows.zip` entpacken und `fcco-Converter.exe` starten. - Windows: fcco-Converter-windows.zip entpacken und fcco-Converter.exe starten.
- **macOS**: `fcco-Converter-macos.zip` entpacken und `fcco-Converter` starten. - macOS: fcco-Converter-macos.zip entpacken und fcco-Converter starten.
FFmpeg wird automatisch beim ersten Start heruntergeladen. Keine weitere Installation nötig. FFmpeg wird automatisch beim ersten Start heruntergeladen. Keine weitere Installation nötig.
@@ -30,66 +47,27 @@ FFmpeg wird automatisch beim ersten Start heruntergeladen. Keine weitere Install
## Updates ## Updates
In der App auf **"Update prüfen"** klicken. Wenn eine neue Version verfügbar ist, wird sie direkt heruntergeladen und installiert. Danach muss die App einmal neu gestartet werden. In der App auf "Update prüfen" klicken. Wenn eine neue Version verfügbar ist, wird sie direkt heruntergeladen und installiert. Danach muss die App einmal neu gestartet werden.
--- ---
## Entwicklung ## Entwicklung
### Voraussetzungen ### Voraussetzungen
- Python 3.11 oder neuer - Python 3.11 oder neuer
- Virtuelle Umgebung empfohlen - Virtuelle Umgebung empfohlen
### Setup ### Setup
```bash
python -m venv .venv python -m venv .venv
source .venv/bin/activate # macOS / Linux source .venv/bin/activate # macOS / Linux
# .venv\Scripts\activate # Windows # .venv\Scripts\activate # Windows
pip install -r requirements.txt pip install -r requirements.txt
```
### Starten ### Starten
```bash
python main.py python main.py
```
### Build (Standalone-Executable) ### Build (Standalone-Executable & ZIP-Erstellung)
```bash
python build.py python build.py
```
Die fertige Datei liegt anschließend im `dist/`-Verzeichnis. Die fertige App und die Release-ZIP-Datei liegen anschließend im dist/ Verzeichnis.
---
## Projektstruktur
```
fcco-Converter/
├── main.py # Einstiegspunkt
├── build.py # Build-Skript (PyInstaller)
├── requirements.txt # Abhängigkeiten
├── icon.ico # Programm-Icon
├── fcco_converter/
│ ├── __init__.py
│ ├── config.py # Einstellungen & Konfiguration
│ ├── converter.py # FFmpeg-Konvertierung
│ ├── metadata.py # ID3-Tags & Cover
│ ├── updater.py # Auto-Update von Gitea Releases
│ └── gui.py # CustomTkinter GUI
└── README.md
```
---
## Hinweise
- Nur `.wav`-Dateien werden als Eingabe akzeptiert.
- Cover-Bilder müssen `.jpg`, `.jpeg` oder `.png` sein.
- Export erfolgt im `.mp3`-Format (192 kbit/s).
- Einstellungen werden in `~/.config/fcco-Converter/` (Linux), `~/Library/Application Support/fcco-Converter/` (macOS) bzw. `%APPDATA%/fcco-Converter/` (Windows) gespeichert.
+2 -1
View File
@@ -86,7 +86,8 @@ def build():
# ZIP-Archiv für das Release erstellen # ZIP-Archiv für das Release erstellen
import tempfile import tempfile
zip_name = f"fcco-Converter-{system.lower()}" sys_name = "macos" if system == "Darwin" else system.lower()
zip_name = f"fcco-Converter-{sys_name}"
zip_path = dist_dir / zip_name zip_path = dist_dir / zip_name
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"app_name": "fcco Converter", "app_name": "fcco Converter",
"app_version": "2.0.1", "app_version": "2.0.2",
"repo_owner": "public", "repo_owner": "public",
"repo_name": "fcco-Converter", "repo_name": "fcco-Converter",
"gitea_api_base": "https://git.joelunger.de/api/v1" "gitea_api_base": "https://git.joelunger.de/api/v1"
+1 -1
View File
@@ -13,7 +13,7 @@ from pathlib import Path
# ---- Globale App-Informationen (aus config.json) ---- # ---- Globale App-Informationen (aus config.json) ----
APP_INFO = { APP_INFO = {
"app_name": "fcco Converter", "app_name": "fcco Converter",
"app_version": "2.0.0", "app_version": "2.0.2",
"repo_owner": "public", "repo_owner": "public",
"repo_name": "fcco-Converter", "repo_name": "fcco-Converter",
"gitea_api_base": "https://git.joelunger.de/api/v1" "gitea_api_base": "https://git.joelunger.de/api/v1"
+2 -1
View File
@@ -205,7 +205,8 @@ def convert_file_entry(
audio_settings = {"output_format": "mp3", "bitrate": "192", "encoding_mode": "CBR"} audio_settings = {"output_format": "mp3", "bitrate": "192", "encoding_mode": "CBR"}
file_path = Path(entry["full_path"]) file_path = Path(entry["full_path"])
title = file_path.stem from .metadata import extract_title_from_filename
title = extract_title_from_filename(file_path.stem)
output_format = audio_settings.get("output_format", "mp3") output_format = audio_settings.get("output_format", "mp3")
try: try:
+42
View File
@@ -4,6 +4,7 @@ fcco-Converter V2 Metadaten-Modul
Hilfsfunktionen für ID3-Tags, Cover-Bilder und Albumname-Generierung. Hilfsfunktionen für ID3-Tags, Cover-Bilder und Albumname-Generierung.
""" """
import re
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
@@ -51,6 +52,47 @@ def extract_event_from_folder(file_path: Path) -> tuple[str, str]:
return "", "" 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 from mutagen.id3 import ID3, APIC, TIT2, TPE1, TALB, TRCK, TDRC
def apply_id3_tags( def apply_id3_tags(