diff --git a/changes/closed-pipe-crash.md b/changes/closed-pipe-crash.md new file mode 100644 index 00000000..06bad486 --- /dev/null +++ b/changes/closed-pipe-crash.md @@ -0,0 +1,4 @@ +type: fixed +area: app + +- SubMiner no longer crashes with "write EPIPE" when the terminal command that started it is stopped with Ctrl+C. diff --git a/changes/youtube-browser-window.md b/changes/youtube-browser-window.md new file mode 100644 index 00000000..3b33ac24 --- /dev/null +++ b/changes/youtube-browser-window.md @@ -0,0 +1,7 @@ +type: added +area: youtube + +- Added a YouTube browser window (`subminer youtube`/`subminer yt`, or tray **Browse YouTube**) that keeps your YouTube login across restarts. +- Clicking a video plays it in mpv instead of the page; middle-click, Shift/Ctrl-click, or the right-click menu queues it in mpv's playlist. +- Queued YouTube videos get the same Japanese subtitle setup when mpv reaches them. +- Closing the YouTube window quits a SubMiner started by `subminer youtube` (after mpv closes, if a video is still playing). diff --git a/changes/youtube-translated-caption-429.md b/changes/youtube-translated-caption-429.md new file mode 100644 index 00000000..aa6acfd1 --- /dev/null +++ b/changes/youtube-translated-caption-429.md @@ -0,0 +1,4 @@ +type: fixed +area: youtube + +- YouTube Japanese subtitles no longer fail with "HTTP 429" on videos where YouTube also lists a machine-translated Japanese track; SubMiner now picks the real track and falls back to yt-dlp if a direct subtitle download is refused. diff --git a/changes/youtube-whisper-subtitles.md b/changes/youtube-whisper-subtitles.md new file mode 100644 index 00000000..ae3cc246 --- /dev/null +++ b/changes/youtube-whisper-subtitles.md @@ -0,0 +1,7 @@ +type: added +area: youtube + +- Added `youtube.subtitleSource`: set it to `whisper` to transcribe YouTube videos with Whisper instead of downloading YouTube's captions. The default stays `youtube`. +- Whisper mode keeps the video paused while it transcribes, with progress in the subtitle generation modal; close the modal to keep watching, or cancel to continue without subtitles. +- The subtitle generation modal (`Ctrl+Shift+G`) now also works on YouTube videos, whatever `youtube.subtitleSource` is set to. +- Whisper mode downloads a small audio-only stream and deletes it once generation ends, or when you switch videos, close mpv, or quit. diff --git a/config.example.jsonc b/config.example.jsonc index 22640179..fe7f4f96 100644 --- a/config.example.jsonc +++ b/config.example.jsonc @@ -682,13 +682,14 @@ // ========================================== // YouTube Playback Settings // Defaults for managed subtitle language preferences and YouTube subtitle loading. - // Hot-reload: primarySubLanguages applies to the next YouTube subtitle load. + // Hot-reload: primarySubLanguages and subtitleSource apply to the next YouTube subtitle load. // ========================================== "youtube": { "primarySubLanguages": [ "ja", "jpn" ], // Comma-separated primary subtitle language priority for managed subtitle auto-selection. + "subtitleSource": "youtube", // Where primary YouTube subtitles come from. Whisper transcribes the audio locally using the subtitleGeneration settings. Values: youtube | whisper "mediaCache": { "mode": "direct", // How YouTube card audio/images are extracted. Values: direct | background "maxHeight": 720 // Maximum video height downloaded for the YouTube background media cache. Set to 0 for unlimited. diff --git a/docs-site/configuration.md b/docs-site/configuration.md index b3de3142..1ec87475 100644 --- a/docs-site/configuration.md +++ b/docs-site/configuration.md @@ -54,7 +54,7 @@ These apply live: - `subtitleStyle`, `subtitleSidebar`, `subtitleSelection`, `keybindings`, `shortcuts` - `logging.level`, `logging.rotation`, `logging.files` -- `secondarySub.defaultMode`, `youtube.primarySubLanguages` +- `secondarySub.defaultMode`, `youtube.primarySubLanguages`, `youtube.subtitleSource` - `mpv.aniskipEnabled`, `mpv.aniskipButtonKey`, `stats.toggleKey`, `stats.markWatchedKey` - `ankiConnect.deck`, `ankiConnect.fields.*`, `ankiConnect.behavior.autoUpdateNewCards` - `ankiConnect.media.normalizeAudio`, `media.mirrorMpvVolume`, `media.reviewTiming` @@ -594,11 +594,12 @@ Settings for mpv instances that SubMiner starts, and for the bundled mpv plugin. ### YouTube playback settings -Language and card-media settings for YouTube playback. YouTube always loads a Japanese primary and English secondary track, preferring manual uploads over auto captions. See [YouTube integration](/youtube-integration). +Subtitle, language, and card-media settings for YouTube playback. With YouTube captions, SubMiner loads a Japanese primary and English secondary track, preferring manual uploads over auto captions. See [YouTube integration](/youtube-integration). | Key | Default | What it does | | ------------------------------ | --------------- | -------------------------------------------------------------------------------------------- | | `youtube.primarySubLanguages` | `["ja", "jpn"]` | Languages that count as a valid primary track, also used for local playback | +| `youtube.subtitleSource` | `"youtube"` | `youtube` downloads YouTube's captions. `whisper` transcribes the audio with Whisper | | `youtube.mediaCache.mode` | `"direct"` | `direct` cuts card media from the stream. `background` downloads the video with yt-dlp first | | `youtube.mediaCache.maxHeight` | `720` | Maximum download height in `background` mode. `0` is unlimited | diff --git a/docs-site/launcher-script.md b/docs-site/launcher-script.md index bd459095..f0741a5e 100644 --- a/docs-site/launcher-script.md +++ b/docs-site/launcher-script.md @@ -48,6 +48,7 @@ App flags such as `--setup` and `--dev` are not launcher flags. Pass them throug | `subminer doctor` | Check the app, mpv, ffmpeg, yt-dlp, pickers, config, and mpv socket | | `subminer doctor --refresh-known-words` | Refresh the known-word cache from Anki | | `subminer settings` | Open the settings window | +| `subminer youtube` / `yt` | Open the [YouTube browser](/youtube-integration#browse-youtube-in-subminer). Videos you pick play in mpv | | `subminer generate-subs [video]` | Generate [Japanese subtitles](/subtitle-generation) with whisper.cpp | | `subminer jellyfin` / `jf` | [Jellyfin](/jellyfin-integration) actions: `setup`, `login`, `logout`, `play`, `discovery` | | `subminer dictionary ` / `dict` | Build a [character dictionary](/character-dictionary) for a file or directory | diff --git a/docs-site/mpv-plugin.md b/docs-site/mpv-plugin.md index 0f05818e..40732c9e 100644 --- a/docs-site/mpv-plugin.md +++ b/docs-site/mpv-plugin.md @@ -124,7 +124,7 @@ script-message subminer-start backend=hyprland socket=/custom/path texthooker=no `log-level` sets SubMiner's log verbosity. Do not use `--debug` for this; it turns on the app's dev mode. -The plugin also handles messages the SubMiner app sends it (`subminer-autoplay-ready`, `subminer-visible-overlay-shown`, `subminer-visible-overlay-hidden`, `subminer-managed-subtitles-loading`, `subminer-overlay-loading-ready`, `subminer-reload-session-bindings`). You do not need to send these yourself. The AniSkip messages are listed on the [AniSkip page](/aniskip-integration#triggering-from-mpv). +The plugin also handles messages the SubMiner app sends it (`subminer-autoplay-ready`, `subminer-autoplay-hold`, `subminer-visible-overlay-shown`, `subminer-visible-overlay-hidden`, `subminer-managed-subtitles-loading`, `subminer-overlay-loading-ready`, `subminer-reload-session-bindings`). You do not need to send these yourself. The AniSkip messages are listed on the [AniSkip page](/aniskip-integration#triggering-from-mpv). ## Auto-start behavior diff --git a/docs-site/public/config.example.jsonc b/docs-site/public/config.example.jsonc index 22640179..fe7f4f96 100644 --- a/docs-site/public/config.example.jsonc +++ b/docs-site/public/config.example.jsonc @@ -682,13 +682,14 @@ // ========================================== // YouTube Playback Settings // Defaults for managed subtitle language preferences and YouTube subtitle loading. - // Hot-reload: primarySubLanguages applies to the next YouTube subtitle load. + // Hot-reload: primarySubLanguages and subtitleSource apply to the next YouTube subtitle load. // ========================================== "youtube": { "primarySubLanguages": [ "ja", "jpn" ], // Comma-separated primary subtitle language priority for managed subtitle auto-selection. + "subtitleSource": "youtube", // Where primary YouTube subtitles come from. Whisper transcribes the audio locally using the subtitleGeneration settings. Values: youtube | whisper "mediaCache": { "mode": "direct", // How YouTube card audio/images are extracted. Values: direct | background "maxHeight": 720 // Maximum video height downloaded for the YouTube background media cache. Set to 0 for unlimited. diff --git a/docs-site/subtitle-generation.md b/docs-site/subtitle-generation.md index 0c2da357..3447d13f 100644 --- a/docs-site/subtitle-generation.md +++ b/docs-site/subtitle-generation.md @@ -10,11 +10,13 @@ When a video has no Japanese subtitles, SubMiner can transcribe its audio into a Downloaded models go to `models/whisper/` next to your SubMiner config file. A configured `modelPath` always wins over the modal's choice. +YouTube videos can use the same setup automatically in place of YouTube's captions. See [Generate subtitles with Whisper](/youtube-integration#generate-subtitles-with-whisper). + The modal's **Local tools** section lists anything missing. After you install a tool or change a path, click **Check again**. ## Generating from the overlay -1. Open a local video in mpv and select its Japanese audio track. +1. Open a local video in mpv and select its Japanese audio track, or play a 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). @@ -24,6 +26,8 @@ The modal shows progress. **Cancel** stops the job. Closing the modal lets the j SubMiner saves `