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:
parent
7e6ffa5899
commit
547dcb358d
1 changed files with 108 additions and 19 deletions
|
|
@ -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):
|
||||
|
|
|
|||
Loading…
Reference in a new issue