Skip to content

fix(youtube): auto-detect caption language instead of hardcoding English - #1

Merged
TTigger merged 1 commit into
mainfrom
fix/youtube-sub-lang-autodetect
Jun 24, 2026
Merged

fix(youtube): auto-detect caption language instead of hardcoding English#1
TTigger merged 1 commit into
mainfrom
fix/youtube-sub-lang-autodetect

Conversation

@TTigger

@TTigger TTigger commented Jun 24, 2026

Copy link
Copy Markdown
Owner

Problem

The yt-dlp provider requested --sub-langs en.* for every video. For a non-English channel this meant transcripts were either dropped, or — worse — distilled from YouTube's English auto-translation, losing the speaker's actual voice. (Found while distilling a Mandarin lecture channel: the mask came out in translated English instead of the speaker's Chinese.)

Fix

Auto-detect the caption language instead of hardcoding it:

  • Probe each video's available tracks with yt-dlp -J (subtitles, automatic_captions, language).
  • New pure, unit-tested pickSubtitleLang() chooses, in order:
    1. an explicit override (MASK_YT_SUBLANGS),
    2. the video's original language (yt-dlp language), human-authored track first,
    3. any human-authored (manual) track,
    4. the original auto-caption track.
  • Machine-translated auto tracks (keyed <target>-<source>, e.g. en-zh-TW) are avoided so a Chinese lecture isn't distilled from its English auto-translation. When language is absent, the original is inferred as the source shared across the <target>-<source> translation keys.
  • MASK_YT_SUBLANGS remains as an escape hatch: an explicit yt-dlp --sub-langs expression (comma lists / zh.* wildcards) passed through verbatim.

Design notes

  • Selection logic is extracted as an exported pure function and tested offline, matching the existing parseVtt / isVideoUrl pattern — the live yt-dlp path stays thin and the injectable-provider contract is unchanged (existing fakes still work).
  • Cost: one extra yt-dlp -J metadata call per video (correctness over speed).

Tests

  • 5 new pickSubtitleLang cases (original-with-manual, original-auto-over-translations, infer-without-language, English-original / lone-auto, override + null). bun test test/youtube.test.ts → 10 pass.
  • bun run typecheck and bun run build green. Full suite unchanged except the new passing tests (any local failures are pre-existing Windows-only path issues; CI runs on Linux).

🤖 Generated with Claude Code

The yt-dlp provider requested `--sub-langs en.*` for every video, so a
non-English channel was either skipped or, worse, distilled from YouTube's
English auto-translation — losing the speaker's actual voice.

Probe each video's tracks (`yt-dlp -J`) and pick the original language via a
new pure, unit-tested `pickSubtitleLang()`: explicit override → original
language (manual track first) → any human-authored track → the original
auto-caption track. Machine-translated tracks (keyed `<target>-<source>`,
e.g. `en-zh-TW`) are avoided. `MASK_YT_SUBLANGS` overrides with an explicit
yt-dlp --sub-langs expression when a specific language is wanted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TTigger
TTigger merged commit d197a56 into main Jun 24, 2026
1 check passed
@TTigger
TTigger deleted the fix/youtube-sub-lang-autodetect branch June 24, 2026 08:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant