fix: Ausgabebenennung auf Amazon-Spec anpassen
MP4: Quell-Stem + _PVD (unveraendert, kein Umschreiben des Titels). Audio-MOVs: Stem ohne Aufloesung/FPS-Token + spezifische Sprach-Tokens der enthaltenen Spuren + _AUDIO. Mehrere Spuren werden als DEU51_DEU20 oder ENG51_ENG20 verbunden. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -195,17 +195,19 @@ preferred_dirs = 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.
|
||||||
|
|
||||||
Dateinamen:
|
Dateinamen (Beispiel fuer Quelldatei `EinCoolerFilm_FTR_1080p2398_DEU20_ENG51_ENG20.mov`):
|
||||||
|
|
||||||
```text
|
```text
|
||||||
TheDarkKnight_DEU20_PVD.mp4
|
EinCoolerFilm_FTR_1080p2398_DEU20_ENG51_ENG20_PVD.mp4
|
||||||
TheDarkKnight_DEU_AUDIO_PCM.mov
|
EinCoolerFilm_FTR_DEU20_AUDIO.mov
|
||||||
TheDarkKnight_OV_AUDIO_PCM.mov
|
EinCoolerFilm_FTR_ENG51_ENG20_AUDIO.mov
|
||||||
```
|
```
|
||||||
|
|
||||||
Der Titel-Teil (vor dem ersten Unterstrich) enthaelt keine Unterstriche – Woerter werden direkt zusammengefuegt. Unterstriche stehen nur im Audio-Suffix (`_DEU20_PVD`, `_DEU_AUDIO_PCM`, `_OV_AUDIO_PCM`).
|
- Das MP4 erhaelt einfach `_PVD` als Suffix – der Quelldateiname bleibt unveraendert.
|
||||||
|
- Die Audio-MOVs verwenden den Stem ohne Aufloesung/FPS-Token, gefolgt von den Sprach-Tokens der enthaltenen Spuren und `_AUDIO`.
|
||||||
|
- Bei mehreren Spuren in einer MOV werden die Tokens mit Unterstrich verbunden (`ENG51_ENG20`).
|
||||||
|
|
||||||
Wenn nur deutsche Tonspuren vorhanden sind, wird keine `..._OV_AUDIO_PCM.mov` erzeugt.
|
Wenn nur deutsche Tonspuren vorhanden sind, wird keine OV-MOV erzeugt.
|
||||||
|
|
||||||
## ProRes-Audio im Dateinamen
|
## ProRes-Audio im Dateinamen
|
||||||
|
|
||||||
|
|||||||
+38
-13
@@ -267,12 +267,17 @@ def strip_audio_tokens(stem: str) -> str:
|
|||||||
return cleaned or stem
|
return cleaned or stem
|
||||||
|
|
||||||
|
|
||||||
|
def strip_resolution_token(stem: str) -> str:
|
||||||
|
"""Entfernt Aufloesung/FPS-Token wie _1080p2398 oder _720p25 aus dem Stem."""
|
||||||
|
cleaned = re.sub(r"_(?:\d{3,4}|4[Kk])[pPiI]\d{2,5}(?=_|$)", "", stem)
|
||||||
|
cleaned = re.sub(r"^(?:\d{3,4}|4[Kk])[pPiI]\d{2,5}_?", "", cleaned)
|
||||||
|
return cleaned.strip("_")
|
||||||
|
|
||||||
|
|
||||||
def extract_title(input_path: str) -> str:
|
def extract_title(input_path: str) -> str:
|
||||||
"""Extrahiert den Titel einheitlich für alle Ausgabedateien (Blu-ray / ProRes / DVD)."""
|
"""Titel aus Blu-ray-Ordnername, bereinigt und ohne Sonderzeichen."""
|
||||||
path = Path(input_path)
|
path = Path(input_path)
|
||||||
path_parts = [p.upper() for p in path.parts]
|
path_parts = [p.upper() for p in path.parts]
|
||||||
|
|
||||||
if "BDMV" in path_parts:
|
|
||||||
bdmv_index = path_parts.index("BDMV")
|
bdmv_index = path_parts.index("BDMV")
|
||||||
try:
|
try:
|
||||||
project_folder = path_parts[bdmv_index - 4]
|
project_folder = path_parts[bdmv_index - 4]
|
||||||
@@ -280,20 +285,38 @@ def extract_title(input_path: str) -> str:
|
|||||||
project_folder = path_parts[bdmv_index - 1] if bdmv_index > 0 else "UNKNOWN"
|
project_folder = path_parts[bdmv_index - 1] if bdmv_index > 0 else "UNKNOWN"
|
||||||
clean_name = re.sub(r"^BEST_", "", project_folder, flags=re.IGNORECASE)
|
clean_name = re.sub(r"^BEST_", "", project_folder, flags=re.IGNORECASE)
|
||||||
words = [w.capitalize() for w in clean_name.split("_") if w.strip()]
|
words = [w.capitalize() for w in clean_name.split("_") if w.strip()]
|
||||||
title = "".join(words)
|
title = re.sub(r"[^A-Za-z0-9]", "", "".join(words))
|
||||||
else:
|
|
||||||
title = strip_audio_tokens(path.stem)
|
|
||||||
|
|
||||||
title = re.sub(r"[^A-Za-z0-9]", "", title)
|
|
||||||
return title or "UNKNOWN_TITLE"
|
return title or "UNKNOWN_TITLE"
|
||||||
|
|
||||||
|
|
||||||
def get_pvd_filename(input_path: str) -> str:
|
def get_pvd_filename(input_path: str) -> str:
|
||||||
return f"{extract_title(input_path)}_DEU20_PVD.mp4"
|
"""MP4-Ausgabename: Quell-Stem + _PVD; bei Blu-ray: konstruierter Titel + _PVD."""
|
||||||
|
path = Path(input_path)
|
||||||
|
if "BDMV" in [p.upper() for p in path.parts]:
|
||||||
|
return f"{extract_title(input_path)}_PVD.mp4"
|
||||||
|
return f"{path.stem}_PVD.mp4"
|
||||||
|
|
||||||
|
|
||||||
def safe_output_stem(input_path: str) -> str:
|
def get_mov_stem(input_path: str) -> str:
|
||||||
|
"""MOV-Basis ohne Aufloesung/FPS und ohne Audio-Token; bei Blu-ray: konstruierter Titel."""
|
||||||
|
path = Path(input_path)
|
||||||
|
if "BDMV" in [p.upper() for p in path.parts]:
|
||||||
return extract_title(input_path)
|
return extract_title(input_path)
|
||||||
|
return strip_resolution_token(strip_audio_tokens(path.stem))
|
||||||
|
|
||||||
|
|
||||||
|
def role_token(role: AudioRole) -> str:
|
||||||
|
"""Rekonstruiert den Dateinamen-Token einer Audiospur, z.B. DEU51 oder ENG20."""
|
||||||
|
if role.layout_from_name:
|
||||||
|
return f"{role.language}{role.layout_from_name.replace('.', '')}"
|
||||||
|
ch = role.effective_channels
|
||||||
|
if ch == 2:
|
||||||
|
return f"{role.language}20"
|
||||||
|
if ch == 6:
|
||||||
|
return f"{role.language}51"
|
||||||
|
if ch == 8:
|
||||||
|
return f"{role.language}71"
|
||||||
|
return f"{role.language}{ch}0"
|
||||||
|
|
||||||
|
|
||||||
def probe_metadata(filepath: str) -> dict:
|
def probe_metadata(filepath: str) -> dict:
|
||||||
@@ -462,11 +485,13 @@ def build_plan(input_file: str, output_dir: str = OUTPUT_BASE_DIR) -> JobPlan:
|
|||||||
|
|
||||||
output_base = Path(output_dir)
|
output_base = Path(output_dir)
|
||||||
pvd_mp4 = str(output_base / get_pvd_filename(input_file))
|
pvd_mp4 = str(output_base / get_pvd_filename(input_file))
|
||||||
output_stem = safe_output_stem(input_file)
|
mov_stem = get_mov_stem(input_file)
|
||||||
german_roles = [role for role in audio_roles if role.is_german]
|
german_roles = [role for role in audio_roles if role.is_german]
|
||||||
original_roles = [role for role in audio_roles if not role.is_german]
|
original_roles = [role for role in audio_roles if not role.is_german]
|
||||||
german_mov = str(output_base / f"{output_stem}_DEU_AUDIO_PCM.mov") if german_roles else None
|
german_tok = "_".join(role_token(r) for r in german_roles)
|
||||||
original_mov = str(output_base / f"{output_stem}_OV_AUDIO_PCM.mov") if original_roles else None
|
original_tok = "_".join(role_token(r) for r in original_roles)
|
||||||
|
german_mov = str(output_base / f"{mov_stem}_{german_tok}_AUDIO.mov") if german_roles else None
|
||||||
|
original_mov = str(output_base / f"{mov_stem}_{original_tok}_AUDIO.mov") if original_roles else None
|
||||||
forced_srt_path = os.path.splitext(input_file)[0] + "_forced.srt"
|
forced_srt_path = os.path.splitext(input_file)[0] + "_forced.srt"
|
||||||
forced_srt = forced_srt_path if os.path.exists(forced_srt_path) else None
|
forced_srt = forced_srt_path if os.path.exists(forced_srt_path) else None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user