From bf4e5bb6097ae16d05f708ee2b34dcd8f3899fa5 Mon Sep 17 00:00:00 2001 From: sudacode Date: Tue, 13 Oct 2026 21:55:28 -0700 Subject: [PATCH] feat(subtitles): generate Japanese subtitles during Jellyfin playback (#294) * feat(subtitles): generate Japanese subtitles during Jellyfin playback - Read the item's original file via toJellyfinOriginalStreamUrl and write output to a temp dir - Transcoded playback uses Jellyfin's audio index and only external references - Show Jellyfin media by title and redact URL tokens in subprocess errors - Update overlay copy, docs, and changelog fragment * fix(subtitles): redact full stream tokens and reuse one Jellyfin output folder * test(subtitles): make Jellyfin output path assertions platform-neutral - Compare dirname/basename via node:path instead of POSIX-only regexes - Assert the full sub-add command uses the generated output path --- changes/jellyfin-subtitle-generation.md | 4 + docs-site/jellyfin-integration.md | 2 + docs-site/subtitle-generation.md | 6 +- docs/architecture/README.md | 2 +- src/core/services/index.ts | 1 + src/core/services/jellyfin.test.ts | 24 +++++ src/core/services/jellyfin.ts | 23 ++++ .../services/subtitle-generation-process.ts | 11 +- src/core/services/subtitle-generation.test.ts | 28 ++++- src/core/services/subtitle-generation.ts | 9 +- src/main.ts | 12 +++ .../subtitle-generation-runtime.test.ts | 100 ++++++++++++++++++ .../runtime/subtitle-generation-runtime.ts | 93 +++++++++++++--- src/renderer/modals/subtitle-generation.ts | 5 +- 14 files changed, 295 insertions(+), 25 deletions(-) create mode 100644 changes/jellyfin-subtitle-generation.md diff --git a/changes/jellyfin-subtitle-generation.md b/changes/jellyfin-subtitle-generation.md new file mode 100644 index 00000000..40880547 --- /dev/null +++ b/changes/jellyfin-subtitle-generation.md @@ -0,0 +1,4 @@ +type: added +area: subtitles + +- Japanese subtitle generation now works while playing a Jellyfin episode. SubMiner reads the original file from the server, saves the subtitles to a cache folder, and loads them into mpv. Direct-play and transcoded playback are both supported. diff --git a/docs-site/jellyfin-integration.md b/docs-site/jellyfin-integration.md index 8bf4424d..b0904307 100644 --- a/docs-site/jellyfin-integration.md +++ b/docs-site/jellyfin-integration.md @@ -23,6 +23,8 @@ SubMiner starts mpv if it is not already running. Pause, seek, stop, and track c SubMiner selects a Japanese subtitle track automatically and resets mpv's subtitle delay to zero. It direct-plays files when it can and asks Jellyfin to transcode the rest. +If an episode has no Japanese subtitles, you can [generate them with Whisper](/subtitle-generation#generating-from-the-overlay) while it plays. + On Windows, casting finds mpv through `mpv.executablePath`, then `SUBMINER_MPV_PATH`, then `PATH`. An invalid `mpv.executablePath` stops mpv from starting. ## Playing from the terminal diff --git a/docs-site/subtitle-generation.md b/docs-site/subtitle-generation.md index 3447d13f..e69fde2a 100644 --- a/docs-site/subtitle-generation.md +++ b/docs-site/subtitle-generation.md @@ -16,7 +16,7 @@ The modal's **Local tools** section lists anything missing. After you install a ## Generating from the overlay -1. Open a local video in mpv and select its Japanese audio track, or play a YouTube video. +1. Open a local video in mpv and select its Japanese audio track, or play a Jellyfin or YouTube video. 2. Press `Ctrl+Shift+G`. If the subtitle sidebar is empty, its **Generate Japanese subtitles** button opens the same modal. 3. Pick a model and download it if needed. 4. Optionally check **Focus on spoken dialogue** (see below). @@ -26,6 +26,8 @@ The modal shows progress. **Cancel** stops the job. Closing the modal lets the j SubMiner saves `