From f68d2589df1905849b70a963f4954382b18456eb Mon Sep 17 00:00:00 2001 From: Melbar Date: Thu, 7 May 2026 18:35:36 +0200 Subject: [PATCH] Use editable INI configuration --- README.md | 91 +++++++++++++++++++++++------------------------- config.ini | 43 +++++++++++++++++++++++ config.json | 34 ------------------ pvd_mezzanine.py | 90 ++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 config.ini delete mode 100644 config.json diff --git a/README.md b/README.md index 964e462..c613596 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Das Tool erzeugt: FFmpeg und FFprobe werden automatisch gesucht: -1. explizite Pfade aus `config.json` +1. explizite Pfade aus `config.ini` 2. `PATH` 3. `C:\Tools\FFMPEG` 4. `C:\Software` @@ -62,7 +62,7 @@ Wenn Tkinter nicht verfuegbar ist, oeffnet das Tool einen nativen Windows-Dateid ## Ausgabe -Das Zielverzeichnis wird ueber `config.json` bestimmt: +Das Zielverzeichnis wird ueber `config.ini` bestimmt: 1. `output.base_dir`, wenn gesetzt 2. erstes vorhandenes Verzeichnis aus `output.preferred_dirs` @@ -70,11 +70,8 @@ Das Zielverzeichnis wird ueber `config.json` bestimmt: Default: -```json -"preferred_dirs": [ - "F:\\VOD", - "H:\\VOD" -] +```ini +preferred_dirs = F:\VOD, H:\VOD ``` Damit wird `F:\VOD` bevorzugt, wenn vorhanden. Sonst wird `H:\VOD` verwendet, wenn vorhanden. @@ -129,8 +126,8 @@ Unterstuetzt werden dreistellige Sprachcodes wie `DEU`, `GER`, `ENG`, `FRA`, `IT ## Video-Regeln -- HD wird mit den HD-Werten aus `config.json` encodiert, standardmaessig `30M`. -- SD wird mit den SD-Werten aus `config.json` encodiert, standardmaessig `8M`. +- HD wird mit den HD-Werten aus `config.ini` encodiert, standardmaessig `30M`. +- SD wird mit den SD-Werten aus `config.ini` encodiert, standardmaessig `8M`. - Interlaced-Material wird mit `bwdif=mode=0:parity=auto` deinterlaced. - Forced Subtitles werden eingebrannt, wenn neben der Quelle eine Datei mit `_forced.srt` liegt. - Farbraum-Metadaten werden auf den Ziel-Farbraum gesetzt. @@ -145,52 +142,50 @@ Film_DEU51_ENG20_forced.srt ## Konfiguration -Die wichtigsten Parameter stehen in [config.json](config.json). +Die wichtigsten Parameter stehen in [config.ini](config.ini). Das Format ist bewusst einfach gehalten: + +- `#` beginnt einen Kommentar +- Werte werden als `name = wert` geschrieben +- mehrere Ordner werden mit Komma getrennt +- leere Werte bedeuten automatische Suche bzw. automatische Auswahl Default: -```json -{ - "ffmpeg": { - "ffmpeg_exe": "", - "ffprobe_exe": "", - "search_dirs": [ - "C:\\Tools\\FFMPEG", - "C:\\Software" - ] - }, - "output": { - "base_dir": "", - "preferred_dirs": [ - "F:\\VOD", - "H:\\VOD" - ] - }, - "video": { - "hd_bitrate": "30M", - "hd_maxrate": "35M", - "hd_bufsize": "50M", - "hd_level": "4.1", - "sd_bitrate": "8M", - "sd_maxrate": "10M", - "sd_bufsize": "15M", - "sd_level": "3.1", - "preset": "slow", - "tune": "film" - }, - "audio": { - "mp4_bitrate": "256k", - "sample_rate": "48000", - "pcm_codec": "pcm_s24le" - } -} +```ini +# Amazon PVD Mezzanine Encoder Konfiguration + +[ffmpeg] +ffmpeg_exe = +ffprobe_exe = +search_dirs = C:\Tools\FFMPEG, C:\Software + +[output] +base_dir = +preferred_dirs = F:\VOD, H:\VOD + +[video] +hd_bitrate = 30M +hd_maxrate = 35M +hd_bufsize = 50M +hd_level = 4.1 +sd_bitrate = 8M +sd_maxrate = 10M +sd_bufsize = 15M +sd_level = 3.1 +preset = slow +tune = film + +[audio] +mp4_bitrate = 256k +sample_rate = 48000 +pcm_codec = pcm_s24le ``` Hinweise: -- `ffmpeg.ffmpeg_exe` und `ffmpeg.ffprobe_exe` koennen leer bleiben, dann wird automatisch gesucht. -- `output.base_dir` ueberschreibt die automatische Zielverzeichniswahl. -- Wenn `config.json` fehlt, wird sie beim Start mit Default-Werten erzeugt. +- `ffmpeg_exe` und `ffprobe_exe` koennen leer bleiben, dann wird automatisch gesucht. +- `base_dir` ueberschreibt die automatische Zielverzeichniswahl. +- Wenn `config.ini` fehlt, wird sie beim Start mit Default-Werten erzeugt. ## Fehlerbilder diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..96cce2e --- /dev/null +++ b/config.ini @@ -0,0 +1,43 @@ +# Amazon PVD Mezzanine Encoder Konfiguration +# Zeilen mit # sind Kommentare. +# Leere Werte bedeuten: automatisch suchen bzw. automatisch waehlen. + +[ffmpeg] +# Optional: feste Pfade setzen. Leer lassen fuer automatische Suche. +ffmpeg_exe = +ffprobe_exe = + +# Suchordner nach PATH. Mehrere Ordner mit Komma trennen. +search_dirs = C:\Tools\FFMPEG, C:\Software + +[output] +# Optional: festes Zielverzeichnis. Leer lassen fuer preferred_dirs. +base_dir = + +# Erstes vorhandenes Verzeichnis wird verwendet. +preferred_dirs = F:\VOD, H:\VOD + +[video] +# HD-PVD-MP4 +hd_bitrate = 30M +hd_maxrate = 35M +hd_bufsize = 50M +hd_level = 4.1 + +# SD-PVD-MP4 +sd_bitrate = 8M +sd_maxrate = 10M +sd_bufsize = 15M +sd_level = 3.1 + +# x264 +preset = slow +tune = film + +[audio] +# Deutscher Stereo-Ton im MP4 +mp4_bitrate = 256k +sample_rate = 48000 + +# Audio-MOVs +pcm_codec = pcm_s24le diff --git a/config.json b/config.json deleted file mode 100644 index 5d2af03..0000000 --- a/config.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "ffmpeg": { - "ffmpeg_exe": "", - "ffprobe_exe": "", - "search_dirs": [ - "C:\\Tools\\FFMPEG", - "C:\\Software" - ] - }, - "output": { - "base_dir": "", - "preferred_dirs": [ - "F:\\VOD", - "H:\\VOD" - ] - }, - "video": { - "hd_bitrate": "30M", - "hd_maxrate": "35M", - "hd_bufsize": "50M", - "hd_level": "4.1", - "sd_bitrate": "8M", - "sd_maxrate": "10M", - "sd_bufsize": "15M", - "sd_level": "3.1", - "preset": "slow", - "tune": "film" - }, - "audio": { - "mp4_bitrate": "256k", - "sample_rate": "48000", - "pcm_codec": "pcm_s24le" - } -} diff --git a/pvd_mezzanine.py b/pvd_mezzanine.py index 1b8ead4..3d1b888 100644 --- a/pvd_mezzanine.py +++ b/pvd_mezzanine.py @@ -1,5 +1,6 @@ from __future__ import annotations +import configparser import json import math import os @@ -27,7 +28,7 @@ except Exception: # 1. KONFIGURATION UND PFADE # ============================================================================= APP_DIR = Path(__file__).resolve().parent -CONFIG_PATH = APP_DIR / "config.json" +CONFIG_PATH = APP_DIR / "config.ini" DEFAULT_CONFIG = { "ffmpeg": { "ffmpeg_exe": "", @@ -64,29 +65,84 @@ DEFAULT_CONFIG = { } -def deep_merge_config(default: dict, override: dict) -> dict: - merged = dict(default) - for key, value in override.items(): - if isinstance(value, dict) and isinstance(merged.get(key), dict): - merged[key] = deep_merge_config(merged[key], value) - else: - merged[key] = value - return merged - - def write_default_config(path: Path) -> None: - path.write_text(json.dumps(DEFAULT_CONFIG, indent=2) + "\n", encoding="utf-8") + path.write_text( + """# Amazon PVD Mezzanine Encoder Konfiguration +# Zeilen mit # sind Kommentare. +# Leere Werte bedeuten: automatisch suchen bzw. automatisch waehlen. + +[ffmpeg] +# Optional: feste Pfade setzen. Leer lassen fuer automatische Suche. +ffmpeg_exe = +ffprobe_exe = + +# Suchordner nach PATH. Mehrere Ordner mit Komma trennen. +search_dirs = C:\\Tools\\FFMPEG, C:\\Software + +[output] +# Optional: festes Zielverzeichnis. Leer lassen fuer preferred_dirs. +base_dir = + +# Erstes vorhandenes Verzeichnis wird verwendet. +preferred_dirs = F:\\VOD, H:\\VOD + +[video] +# HD-PVD-MP4 +hd_bitrate = 30M +hd_maxrate = 35M +hd_bufsize = 50M +hd_level = 4.1 + +# SD-PVD-MP4 +sd_bitrate = 8M +sd_maxrate = 10M +sd_bufsize = 15M +sd_level = 3.1 + +# x264 +preset = slow +tune = film + +[audio] +# Deutscher Stereo-Ton im MP4 +mp4_bitrate = 256k +sample_rate = 48000 + +# Audio-MOVs +pcm_codec = pcm_s24le +""", + encoding="utf-8", + ) + + +def split_config_list(value: str) -> list[str]: + return [part.strip() for part in value.split(",") if part.strip()] def load_config() -> dict: if not CONFIG_PATH.exists(): write_default_config(CONFIG_PATH) return DEFAULT_CONFIG - try: - user_config = json.loads(CONFIG_PATH.read_text(encoding="utf-8")) - except json.JSONDecodeError as exc: - raise RuntimeError(f"config.json ist ungueltig: {exc}") from exc - return deep_merge_config(DEFAULT_CONFIG, user_config) + + parser = configparser.ConfigParser() + parser.read(CONFIG_PATH, encoding="utf-8") + config = { + section: dict(values) + for section, values in DEFAULT_CONFIG.items() + } + + for section, defaults in DEFAULT_CONFIG.items(): + if not parser.has_section(section): + continue + for key, default_value in defaults.items(): + if not parser.has_option(section, key): + continue + raw_value = parser.get(section, key).strip() + if isinstance(default_value, list): + config[section][key] = split_config_list(raw_value) + else: + config[section][key] = raw_value + return config def find_executable(name: str, configured_path: str, search_dirs: list[str]) -> str: