Use editable INI configuration
This commit is contained in:
@@ -25,7 +25,7 @@ Das Tool erzeugt:
|
|||||||
|
|
||||||
FFmpeg und FFprobe werden automatisch gesucht:
|
FFmpeg und FFprobe werden automatisch gesucht:
|
||||||
|
|
||||||
1. explizite Pfade aus `config.json`
|
1. explizite Pfade aus `config.ini`
|
||||||
2. `PATH`
|
2. `PATH`
|
||||||
3. `C:\Tools\FFMPEG`
|
3. `C:\Tools\FFMPEG`
|
||||||
4. `C:\Software`
|
4. `C:\Software`
|
||||||
@@ -62,7 +62,7 @@ Wenn Tkinter nicht verfuegbar ist, oeffnet das Tool einen nativen Windows-Dateid
|
|||||||
|
|
||||||
## Ausgabe
|
## Ausgabe
|
||||||
|
|
||||||
Das Zielverzeichnis wird ueber `config.json` bestimmt:
|
Das Zielverzeichnis wird ueber `config.ini` bestimmt:
|
||||||
|
|
||||||
1. `output.base_dir`, wenn gesetzt
|
1. `output.base_dir`, wenn gesetzt
|
||||||
2. erstes vorhandenes Verzeichnis aus `output.preferred_dirs`
|
2. erstes vorhandenes Verzeichnis aus `output.preferred_dirs`
|
||||||
@@ -70,11 +70,8 @@ Das Zielverzeichnis wird ueber `config.json` bestimmt:
|
|||||||
|
|
||||||
Default:
|
Default:
|
||||||
|
|
||||||
```json
|
```ini
|
||||||
"preferred_dirs": [
|
preferred_dirs = F:\VOD, H:\VOD
|
||||||
"F:\\VOD",
|
|
||||||
"H:\\VOD"
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Damit wird `F:\VOD` bevorzugt, wenn vorhanden. Sonst wird `H:\VOD` verwendet, wenn vorhanden.
|
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
|
## Video-Regeln
|
||||||
|
|
||||||
- HD wird mit den HD-Werten aus `config.json` encodiert, standardmaessig `30M`.
|
- HD wird mit den HD-Werten aus `config.ini` encodiert, standardmaessig `30M`.
|
||||||
- SD wird mit den SD-Werten aus `config.json` encodiert, standardmaessig `8M`.
|
- SD wird mit den SD-Werten aus `config.ini` encodiert, standardmaessig `8M`.
|
||||||
- Interlaced-Material wird mit `bwdif=mode=0:parity=auto` deinterlaced.
|
- Interlaced-Material wird mit `bwdif=mode=0:parity=auto` deinterlaced.
|
||||||
- Forced Subtitles werden eingebrannt, wenn neben der Quelle eine Datei mit `_forced.srt` liegt.
|
- Forced Subtitles werden eingebrannt, wenn neben der Quelle eine Datei mit `_forced.srt` liegt.
|
||||||
- Farbraum-Metadaten werden auf den Ziel-Farbraum gesetzt.
|
- Farbraum-Metadaten werden auf den Ziel-Farbraum gesetzt.
|
||||||
@@ -145,52 +142,50 @@ Film_DEU51_ENG20_forced.srt
|
|||||||
|
|
||||||
## Konfiguration
|
## 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:
|
Default:
|
||||||
|
|
||||||
```json
|
```ini
|
||||||
{
|
# Amazon PVD Mezzanine Encoder Konfiguration
|
||||||
"ffmpeg": {
|
|
||||||
"ffmpeg_exe": "",
|
[ffmpeg]
|
||||||
"ffprobe_exe": "",
|
ffmpeg_exe =
|
||||||
"search_dirs": [
|
ffprobe_exe =
|
||||||
"C:\\Tools\\FFMPEG",
|
search_dirs = C:\Tools\FFMPEG, C:\Software
|
||||||
"C:\\Software"
|
|
||||||
]
|
[output]
|
||||||
},
|
base_dir =
|
||||||
"output": {
|
preferred_dirs = F:\VOD, H:\VOD
|
||||||
"base_dir": "",
|
|
||||||
"preferred_dirs": [
|
[video]
|
||||||
"F:\\VOD",
|
hd_bitrate = 30M
|
||||||
"H:\\VOD"
|
hd_maxrate = 35M
|
||||||
]
|
hd_bufsize = 50M
|
||||||
},
|
hd_level = 4.1
|
||||||
"video": {
|
sd_bitrate = 8M
|
||||||
"hd_bitrate": "30M",
|
sd_maxrate = 10M
|
||||||
"hd_maxrate": "35M",
|
sd_bufsize = 15M
|
||||||
"hd_bufsize": "50M",
|
sd_level = 3.1
|
||||||
"hd_level": "4.1",
|
preset = slow
|
||||||
"sd_bitrate": "8M",
|
tune = film
|
||||||
"sd_maxrate": "10M",
|
|
||||||
"sd_bufsize": "15M",
|
[audio]
|
||||||
"sd_level": "3.1",
|
mp4_bitrate = 256k
|
||||||
"preset": "slow",
|
sample_rate = 48000
|
||||||
"tune": "film"
|
pcm_codec = pcm_s24le
|
||||||
},
|
|
||||||
"audio": {
|
|
||||||
"mp4_bitrate": "256k",
|
|
||||||
"sample_rate": "48000",
|
|
||||||
"pcm_codec": "pcm_s24le"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Hinweise:
|
Hinweise:
|
||||||
|
|
||||||
- `ffmpeg.ffmpeg_exe` und `ffmpeg.ffprobe_exe` koennen leer bleiben, dann wird automatisch gesucht.
|
- `ffmpeg_exe` und `ffprobe_exe` koennen leer bleiben, dann wird automatisch gesucht.
|
||||||
- `output.base_dir` ueberschreibt die automatische Zielverzeichniswahl.
|
- `base_dir` ueberschreibt die automatische Zielverzeichniswahl.
|
||||||
- Wenn `config.json` fehlt, wird sie beim Start mit Default-Werten erzeugt.
|
- Wenn `config.ini` fehlt, wird sie beim Start mit Default-Werten erzeugt.
|
||||||
|
|
||||||
## Fehlerbilder
|
## Fehlerbilder
|
||||||
|
|
||||||
|
|||||||
+43
@@ -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
|
||||||
-34
@@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+73
-17
@@ -1,5 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import configparser
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
@@ -27,7 +28,7 @@ except Exception:
|
|||||||
# 1. KONFIGURATION UND PFADE
|
# 1. KONFIGURATION UND PFADE
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
APP_DIR = Path(__file__).resolve().parent
|
APP_DIR = Path(__file__).resolve().parent
|
||||||
CONFIG_PATH = APP_DIR / "config.json"
|
CONFIG_PATH = APP_DIR / "config.ini"
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"ffmpeg": {
|
"ffmpeg": {
|
||||||
"ffmpeg_exe": "",
|
"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:
|
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:
|
def load_config() -> dict:
|
||||||
if not CONFIG_PATH.exists():
|
if not CONFIG_PATH.exists():
|
||||||
write_default_config(CONFIG_PATH)
|
write_default_config(CONFIG_PATH)
|
||||||
return DEFAULT_CONFIG
|
return DEFAULT_CONFIG
|
||||||
try:
|
|
||||||
user_config = json.loads(CONFIG_PATH.read_text(encoding="utf-8"))
|
parser = configparser.ConfigParser()
|
||||||
except json.JSONDecodeError as exc:
|
parser.read(CONFIG_PATH, encoding="utf-8")
|
||||||
raise RuntimeError(f"config.json ist ungueltig: {exc}") from exc
|
config = {
|
||||||
return deep_merge_config(DEFAULT_CONFIG, user_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:
|
def find_executable(name: str, configured_path: str, search_dirs: list[str]) -> str:
|
||||||
|
|||||||
Reference in New Issue
Block a user