fix: prefer English captions when the source language is unknown

Without a reported language, selection fell back to alphabetical order,
so an English video with de + en manual tracks got a German transcript.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
bradautomates 2026-09-25 09:37:07 +10:00
parent fdbffd1c2e
commit 285d7f46eb
3 changed files with 13 additions and 3 deletions

View File

@ -9,7 +9,7 @@ All notable changes to `/watch` are documented here.
- Setup wizard asks for the engine first; a Gemini-only setup no longer requires `ffmpeg`/`yt-dlp` for YouTube URLs.
- Managed, optional WhisperX 3.8.6 setup with uv, a separate Python 3.12 environment, cache warm-up, recoverable installation state, and local CPU transcription. Default model: small, int8, batch 8; language and timeout are configurable. Local failures never select a cloud provider.
- One-time fallback selection in the skill wizard: WhisperX, Groq, OpenAI, or captions only. Existing installations retain the `auto` cloud-key preference.
- Original-language caption selection and provenance, `--sub-lang`, and explicit cookie-file/browser options shared across downloader stages.
- Original-language caption selection and provenance (English preferred when the source language is unknown), `--sub-lang`, and explicit cookie-file/browser options shared across downloader stages.
- Reports for unavailable modalities, no speech, and missing cloud-transcription intervals. Offline dependency diagnostics and a cross-platform CI gate for release publication.
### Fixed

View File

@ -106,8 +106,10 @@ def select_caption(info: dict, language: str = 'auto') -> dict | None:
if language != 'auto':
return key == target or base == target or ('-' not in language and base.split('-')[0] == target)
return target and (base == target or base.split('-')[0] == str(target).split('-')[0])
def english_first(key): # Unknown source language: prefer English over alphabetical order.
return key.removesuffix('-orig').split('-')[0] != 'en', key
for kind, tracks in (('manual', manual), ('automatic', automatic)):
keys = sorted(tracks)
keys = sorted(tracks, key=english_first)
if target:
keys = sorted((k for k in keys if matches(k)), key=lambda k: (k != target, k != f'{target}-orig', k))
if keys:
@ -124,7 +126,7 @@ def select_caption(info: dict, language: str = 'auto') -> dict | None:
if language == 'auto':
for kind, tracks in (('manual', manual), ('automatic', automatic)):
if tracks:
key = sorted(tracks)[0]
key = min(tracks, key=english_first)
return {'key': key, 'language': key.removesuffix('-orig'), 'kind': kind, 'provenance': 'unknown'}
return None

View File

@ -23,6 +23,14 @@ def test_original_track_overrides_dubbed_metadata(language):
assert download.select_caption(info)['key'] == f'{language}-orig'
def test_unknown_language_prefers_english():
# "Me at the zoo" reports no language and has manual de + en tracks.
picked = download.select_caption({'extractor_key': 'Youtube', 'subtitles': _tracks('de', 'en')})
assert (picked['key'], picked['provenance']) == ('en', 'unknown')
assert download.select_caption({'automatic_captions': _tracks('af', 'en-GB', 'zu')})['key'] == 'en-GB'
assert download.select_caption({'subtitles': _tracks('de', 'fr')})['key'] == 'de'
def test_requested_translation_and_unknown_source():
info = {'extractor_key': 'Youtube', 'automatic_captions': _tracks('ko-orig', 'en')}
assert download.select_caption(info, 'en')['provenance'] == 'requested translation'