fix: Originalsprache bei Videos mit KI-synchronisierten Tonspuren

Gefunden mit einem englischen Video (0LmCveTM788): ohne -l wurde Arabisch
gewählt, denn jede der 20 Synchron-Tonspuren hat eine eigene „-orig“-Spur.
- original_language(): aus „language“, sonst Tonspur mit „original“, sonst
  die einzige „-orig“-Spur
- Automatische Untertitel nur in der Originalsprache (keine Synchronisation)
- Sprachen auch mit Region: „en“ findet manuelle Untertitel „en-US“

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Dieter Schlüter 2026-10-10 20:28:05 +02:00
commit 547dcb358d

View file

@ -31,39 +31,66 @@ def fetch_info(url):
return json.loads(result.stdout)
def choose_track(info, lang):
"""Pick the subtitle track for `lang`: (track name, is_auto) or None.
Manual subtitles come first. Of the automatic captions only the original
language ("<lang>-orig") is used: plain "<lang>" there is a machine
translation whenever the video is in another language.
"""
if lang in (info.get("subtitles") or {}):
return lang, False
if f"{lang}-orig" in (info.get("automatic_captions") or {}):
return f"{lang}-orig", True
return None
def base_language(code):
""""en-US" -> "en", "de-orig" -> "de"."""
return code.removesuffix("-orig").split("-")[0].lower()
def original_language(info):
"""Language of the video's audio, or None if yt-dlp does not know it.
"""Language of the video's original audio, or None if unknown.
YouTube marks the automatic captions in the spoken language with "-orig".
Not simply the first "<lang>-orig" caption track: videos with AI-dubbed
audio tracks have such a track for every dubbed language.
"""
for name in info.get("automatic_captions") or {}:
if name.endswith("-orig"):
return name.removesuffix("-orig")
return info.get("language")
if info.get("language"):
return info["language"]
for fmt in info.get("formats") or []:
if "original" in (fmt.get("format_note") or "") and fmt.get("language"):
return fmt["language"]
originals = [n for n in info.get("automatic_captions") or {} if n.endswith("-orig")]
return originals[0].removesuffix("-orig") if len(originals) == 1 else None
def choose_track(info, lang):
"""Pick the subtitle track for `lang`: (track name, is_auto) or None.
Manual subtitles come first, also with a region ("en" finds "en-US").
Automatic captions are used only in the language of the original audio
("<lang>-orig"): plain "<lang>" is a machine translation, and "-orig"
tracks of other languages belong to AI-dubbed audio tracks.
"""
manual = info.get("subtitles") or {}
if lang in manual:
return lang, False
same_language = sorted(n for n in manual if base_language(n) == base_language(lang))
if same_language:
return same_language[0], False
original = original_language(info)
if original and base_language(original) != base_language(lang):
return None
auto = info.get("automatic_captions") or {}
candidates = [f"{lang}-orig", f"{base_language(lang)}-orig"] + sorted(
n for n in auto
if n.endswith("-orig") and base_language(n) == base_language(lang)
)
for name in candidates:
if name in auto:
return name, True
return None
def available_tracks(info):
"""Manual tracks and the automatic ones usable for this program."""
manual = sorted((info.get("subtitles") or {}).keys())
original = sorted(
original = original_language(info)
automatic = sorted(
name.removesuffix("-orig")
for name in (info.get("automatic_captions") or {})
if name.endswith("-orig")
and (original is None or base_language(name) == base_language(original))
)
return manual, original
return manual, automatic
def no_track_message(info, lang):