mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-25 00:11:26 -07:00
docs: update youtube playback docs and config copy
This commit is contained in:
@@ -68,7 +68,7 @@ Local stats dashboard — watch time, anime library, vocabulary growth, mining t
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>YouTube</b></td>
|
<td><b>YouTube</b></td>
|
||||||
<td>App-owned subtitle picker with downloaded/native track selection and local fallback generation</td>
|
<td>Auto-loaded yt-dlp subtitle tracks with manual retry picker on demand</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>AniList</b></td>
|
<td><b>AniList</b></td>
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ area: launcher
|
|||||||
|
|
||||||
- Changed app-owned YouTube playback to auto-load the default primary subtitle and a best-effort secondary subtitle at startup instead of forcing the picker modal first.
|
- Changed app-owned YouTube playback to auto-load the default primary subtitle and a best-effort secondary subtitle at startup instead of forcing the picker modal first.
|
||||||
- Kept startup playback gating tied only to primary subtitle load and tokenization readiness; secondary failures no longer block resume.
|
- Kept startup playback gating tied only to primary subtitle load and tokenization readiness; secondary failures no longer block resume.
|
||||||
- Added a default `Ctrl+Shift+J` keybinding that opens the YouTube subtitle picker manually during active YouTube playback.
|
- Added a default `Ctrl+Alt+C` keybinding that opens the YouTube subtitle picker manually during active YouTube playback.
|
||||||
- Routed primary YouTube subtitle auto-load failures through the configured notification output path so failed startup still resumes cleanly.
|
- Routed primary YouTube subtitle auto-load failures through the configured notification output path so failed startup still resumes cleanly.
|
||||||
|
- Kept `youtubeSubgen.whisper*` settings as legacy compatibility configuration only; normal startup now resolves tracks through YouTube source download/selection.
|
||||||
- Fixed startup-launched YouTube playback so primary subtitle overlay updates continue after auto-load completes.
|
- Fixed startup-launched YouTube playback so primary subtitle overlay updates continue after auto-load completes.
|
||||||
- Fixed auto-loaded YouTube primary subtitles so parsed cues appear in the subtitle sidebar without needing a manual picker retry.
|
- Fixed auto-loaded YouTube primary subtitles so parsed cues appear in the subtitle sidebar without needing a manual picker retry.
|
||||||
|
|||||||
@@ -187,7 +187,7 @@
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
// Secondary Subtitles
|
// Secondary Subtitles
|
||||||
// Dual subtitle track options.
|
// Dual subtitle track options.
|
||||||
// Used by subminer YouTube subtitle generation as secondary language preferences.
|
// Used by the YouTube subtitle loading flow as secondary language preferences.
|
||||||
// Hot-reload: defaultMode updates live while SubMiner is running.
|
// Hot-reload: defaultMode updates live while SubMiner is running.
|
||||||
// ==========================================
|
// ==========================================
|
||||||
"secondarySub": {
|
"secondarySub": {
|
||||||
@@ -414,24 +414,24 @@
|
|||||||
}, // Jimaku API configuration and defaults.
|
}, // Jimaku API configuration and defaults.
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// YouTube Subtitle Generation
|
// YouTube Playback Settings
|
||||||
// Defaults for SubMiner YouTube subtitle generation.
|
// Defaults for SubMiner YouTube subtitle loading and languages.
|
||||||
// ==========================================
|
// ==========================================
|
||||||
"youtubeSubgen": {
|
"youtubeSubgen": {
|
||||||
"whisperBin": "", // Path to whisper.cpp CLI used as fallback transcription engine.
|
"whisperBin": "", // Legacy compatibility path kept for external subtitle fallback tools; not used by default.
|
||||||
"whisperModel": "", // Path to whisper model used for fallback transcription.
|
"whisperModel": "", // Legacy compatibility model path kept for external subtitle fallback tooling; not used by default.
|
||||||
"whisperVadModel": "", // Path to optional whisper VAD model used for subtitle generation.
|
"whisperVadModel": "", // Legacy compatibility VAD path kept for external subtitle fallback tooling; not used by default.
|
||||||
"whisperThreads": 4, // Thread count passed to whisper.cpp subtitle generation runs.
|
"whisperThreads": 4, // Legacy thread tuning for subtitle fallback tooling; not used by default.
|
||||||
"fixWithAi": false, // Use shared AI provider to post-process whisper-generated YouTube subtitles. Values: true | false
|
"fixWithAi": false, // Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default. Values: true | false
|
||||||
"ai": {
|
"ai": {
|
||||||
"model": "", // Optional model override for YouTube subtitle AI post-processing.
|
"model": "", // Optional model override for legacy subtitle fallback post-processing; not used by default.
|
||||||
"systemPrompt": "" // Optional system prompt override for YouTube subtitle AI post-processing.
|
"systemPrompt": "" // Optional system prompt override for legacy subtitle fallback post-processing; not used by default.
|
||||||
}, // Ai setting.
|
}, // Ai setting.
|
||||||
"primarySubLanguages": [
|
"primarySubLanguages": [
|
||||||
"ja",
|
"ja",
|
||||||
"jpn"
|
"jpn"
|
||||||
] // Comma-separated primary subtitle language priority used by the launcher.
|
] // Comma-separated primary subtitle language priority used by the launcher.
|
||||||
}, // Defaults for SubMiner YouTube subtitle generation.
|
}, // Defaults for SubMiner YouTube subtitle loading and languages.
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// Anilist
|
// Anilist
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
## v0.9.0 (2026-03-22)
|
## v0.9.0 (2026-03-22)
|
||||||
- Added an app-owned YouTube subtitle flow that boots mpv paused, auto-loads the default primary subtitle plus a best-effort secondary subtitle, and resumes once the primary subtitle is loaded and tokenized.
|
- Added an app-owned YouTube subtitle flow that boots mpv paused, auto-loads the default primary subtitle plus a best-effort secondary subtitle, and resumes once the primary subtitle is loaded and tokenized.
|
||||||
- Added a manual YouTube subtitle picker on `Ctrl+Shift+J` so subtitle selection can be retried on demand during active YouTube playback.
|
- Added a manual YouTube subtitle picker on `Ctrl+Alt+C` so subtitle selection can be retried on demand during active YouTube playback.
|
||||||
- Added explicit launcher/app YouTube subtitle modes `download` and `generate`, with `download` as the default path.
|
- Standardized on the default YouTube subtitle auto-load startup flow and removed explicit subtitle mode switching.
|
||||||
- Disabled mpv native YouTube subtitle auto-loading for the app-owned flow so injected external subtitle files stay authoritative.
|
- Disabled conflicting mpv native subtitle auto-selection for the app-owned flow so injected explicit tracks stay authoritative.
|
||||||
- Added OSD status updates covering YouTube playback startup, subtitle acquisition, and subtitle loading.
|
- Added OSD status updates covering YouTube playback startup, subtitle acquisition, and subtitle loading.
|
||||||
- Improved sidebar startup/resume behavior and overlay/sidebar subtitle synchronization.
|
- Improved sidebar startup/resume behavior and overlay/sidebar subtitle synchronization.
|
||||||
|
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ The configuration file includes several main sections:
|
|||||||
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
||||||
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
||||||
- [**Stats Dashboard**](#stats-dashboard) - Local dashboard and overlay for immersion progress
|
- [**Stats Dashboard**](#stats-dashboard) - Local dashboard and overlay for immersion progress
|
||||||
- [**YouTube Subtitle Generation**](#youtube-subtitle-generation) - Launcher defaults for yt-dlp + local whisper fallback
|
- [**YouTube Playback Settings**](#youtube-playback-settings) - Defaults for YouTube subtitle loading
|
||||||
|
|
||||||
## Core Settings
|
## Core Settings
|
||||||
|
|
||||||
@@ -469,7 +469,7 @@ See `config.example.jsonc` for detailed configuration options and more examples.
|
|||||||
| `Space` | `["cycle", "pause"]` | Toggle pause |
|
| `Space` | `["cycle", "pause"]` | Toggle pause |
|
||||||
| `KeyJ` | `["cycle", "sid"]` | Cycle primary subtitle track |
|
| `KeyJ` | `["cycle", "sid"]` | Cycle primary subtitle track |
|
||||||
| `Shift+KeyJ` | `["cycle", "secondary-sid"]` | Cycle secondary subtitle track |
|
| `Shift+KeyJ` | `["cycle", "secondary-sid"]` | Cycle secondary subtitle track |
|
||||||
| `Ctrl+Shift+KeyJ` | `["__youtube-picker-open"]` | Open the manual YouTube subtitle picker |
|
| `Ctrl+Alt+KeyC` | `["__youtube-picker-open"]` | Open the manual YouTube subtitle picker |
|
||||||
| `ArrowRight` | `["seek", 5]` | Seek forward 5 seconds |
|
| `ArrowRight` | `["seek", 5]` | Seek forward 5 seconds |
|
||||||
| `ArrowLeft` | `["seek", -5]` | Seek backward 5 seconds |
|
| `ArrowLeft` | `["seek", -5]` | Seek backward 5 seconds |
|
||||||
| `ArrowUp` | `["seek", 60]` | Seek forward 60 seconds |
|
| `ArrowUp` | `["seek", 60]` | Seek forward 60 seconds |
|
||||||
@@ -741,7 +741,7 @@ Palette controls:
|
|||||||
### Shared AI Provider
|
### Shared AI Provider
|
||||||
|
|
||||||
Shared OpenAI-compatible transport settings live at the top level under `ai`.
|
Shared OpenAI-compatible transport settings live at the top level under `ai`.
|
||||||
Anki and YouTube subtitle cleanup both read this provider, then apply feature-local overrides where supported.
|
Anki reads this provider directly. Legacy subtitle fallback keeps the same provider shape for compatibility, then applies feature-local overrides where supported.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -765,10 +765,10 @@ Anki and YouTube subtitle cleanup both read this provider, then apply feature-lo
|
|||||||
| `systemPrompt` | string | Optional system prompt override for shared provider workflows |
|
| `systemPrompt` | string | Optional system prompt override for shared provider workflows |
|
||||||
| `requestTimeoutMs` | integer milliseconds | Shared request timeout (default: `15000`) |
|
| `requestTimeoutMs` | integer milliseconds | Shared request timeout (default: `15000`) |
|
||||||
|
|
||||||
SubMiner uses the shared provider in two places:
|
SubMiner uses the shared provider for:
|
||||||
|
|
||||||
- Anki translation/enrichment when `ankiConnect.ai.enabled` is `true`
|
- Anki translation/enrichment when `ankiConnect.ai.enabled` is `true`
|
||||||
- YouTube whisper subtitle post-processing when `youtubeSubgen.fixWithAi` is `true`
|
- Legacy subtitle fallback compatibility when `youtubeSubgen.fixWithAi` is `true`
|
||||||
|
|
||||||
### AnkiConnect
|
### AnkiConnect
|
||||||
|
|
||||||
@@ -1326,22 +1326,13 @@ Usage notes:
|
|||||||
- The dashboard reads from the same immersion-tracking database, so keep `immersionTracking.enabled` on if you want data to appear.
|
- The dashboard reads from the same immersion-tracking database, so keep `immersionTracking.enabled` on if you want data to appear.
|
||||||
- The UI includes Overview, Library, Trends, Vocabulary, and Sessions tabs.
|
- The UI includes Overview, Library, Trends, Vocabulary, and Sessions tabs.
|
||||||
|
|
||||||
### YouTube Subtitle Generation
|
### YouTube Playback Settings
|
||||||
|
|
||||||
Set defaults used by the `subminer` launcher for YouTube subtitle generation:
|
Set defaults used by the `subminer` launcher for YouTube subtitle loading:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"youtubeSubgen": {
|
"youtubeSubgen": {
|
||||||
"whisperBin": "/path/to/whisper-cli",
|
|
||||||
"whisperModel": "/path/to/ggml-model.bin",
|
|
||||||
"whisperVadModel": "/path/to/ggml-vad.bin",
|
|
||||||
"whisperThreads": 4,
|
|
||||||
"fixWithAi": false,
|
|
||||||
"ai": {
|
|
||||||
"model": "openai/gpt-4o-mini",
|
|
||||||
"systemPrompt": "Fix subtitle mistakes only."
|
|
||||||
},
|
|
||||||
"primarySubLanguages": ["ja", "jpn"]
|
"primarySubLanguages": ["ja", "jpn"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1349,28 +1340,20 @@ Set defaults used by the `subminer` launcher for YouTube subtitle generation:
|
|||||||
|
|
||||||
| Option | Values | Description |
|
| Option | Values | Description |
|
||||||
| --------------------- | -------------------- | ---------------------------------------------------------------------------------------------- |
|
| --------------------- | -------------------- | ---------------------------------------------------------------------------------------------- |
|
||||||
| `whisperBin` | string path | Path to `whisper.cpp` CLI binary used as fallback transcription engine |
|
| `primarySubLanguages` | string[] | Primary subtitle language priority for YouTube auto-loading (default `["ja", "jpn"]`) |
|
||||||
| `whisperModel` | string path | Path to whisper model used by fallback transcription |
|
|
||||||
| `whisperVadModel` | string path | Optional whisper VAD model path |
|
|
||||||
| `whisperThreads` | integer | Thread count passed to whisper runs |
|
|
||||||
| `fixWithAi` | `true`, `false` | Run shared AI post-processing on whisper-generated subtitles |
|
|
||||||
| `ai.model` | string | Optional model override for YouTube AI subtitle cleanup |
|
|
||||||
| `ai.systemPrompt` | string | Optional system prompt override for YouTube AI subtitle cleanup |
|
|
||||||
| `primarySubLanguages` | string[] | Primary subtitle language priority for YouTube subtitle generation (default `["ja", "jpn"]`) |
|
|
||||||
|
|
||||||
Launcher behavior:
|
Current launcher behavior:
|
||||||
|
|
||||||
- For YouTube URLs, SubMiner auto-loads the default primary subtitle plus a best-effort secondary subtitle during startup.
|
- For YouTube URLs, SubMiner probes subtitle tracks with yt-dlp and loads auto-selected tracks before regular playback starts.
|
||||||
- SubMiner probes manual/native YouTube subtitle tracks first.
|
- SubMiner loads the primary subtitle plus a best-effort secondary subtitle.
|
||||||
- Missing tracks fall back to local `whisper.cpp`.
|
- Playback waits only for primary subtitle readiness; secondary failures do not block playback.
|
||||||
- Playback waits only for the primary subtitle to load and tokenize; startup secondary failures never block playback.
|
- English secondary subtitles are selected from `secondarySub.secondarySubLanguages` when primary language matches are unavailable.
|
||||||
- English secondary subtitles can use whisper translate fallback when no manual track exists.
|
- If primary subtitle loading fails, use `Ctrl+Alt+C` to open the subtitle modal and pick a track.
|
||||||
- If `fixWithAi` is enabled, only whisper-generated `.srt` output is post-processed with the shared top-level `ai` provider.
|
|
||||||
|
|
||||||
Language targets are derived from subtitle config:
|
Language targets are derived from subtitle config:
|
||||||
|
|
||||||
- primary track: `youtubeSubgen.primarySubLanguages` (falls back to `["ja","jpn"]`)
|
- primary track: `youtubeSubgen.primarySubLanguages` (falls back to `["ja","jpn"]`)
|
||||||
- secondary track: `secondarySub.secondarySubLanguages` (falls back to English when empty)
|
- secondary track: `secondarySub.secondarySubLanguages` (falls back to English when empty)
|
||||||
- Subtitle files are generated or downloaded before mpv starts; the older launcher mode switch has been removed.
|
- Tracks are resolved and loaded before mpv starts; the older launcher mode switch has been removed.
|
||||||
|
|
||||||
Precedence for launcher defaults is: CLI flag > environment variable > `config.jsonc` > built-in default.
|
Precedence for launcher defaults is: CLI flag > environment variable > `config.jsonc` > built-in default.
|
||||||
|
|||||||
@@ -231,13 +231,13 @@ Run `make help` for a full list of targets. Key ones:
|
|||||||
| `SUBMINER_ROFI_THEME` | Override rofi theme path for launcher picker |
|
| `SUBMINER_ROFI_THEME` | Override rofi theme path for launcher picker |
|
||||||
| `SUBMINER_LOG_LEVEL` | Override app logger level (`debug`, `info`, `warn`, `error`) |
|
| `SUBMINER_LOG_LEVEL` | Override app logger level (`debug`, `info`, `warn`, `error`) |
|
||||||
| `SUBMINER_MPV_LOG` | Override mpv/app shared log file path |
|
| `SUBMINER_MPV_LOG` | Override mpv/app shared log file path |
|
||||||
| `SUBMINER_WHISPER_BIN` | Override `youtubeSubgen.whisperBin` for launcher |
|
| `SUBMINER_WHISPER_BIN` | Override legacy `youtubeSubgen.whisperBin` fallback compatibility path |
|
||||||
| `SUBMINER_WHISPER_MODEL` | Override `youtubeSubgen.whisperModel` for launcher |
|
| `SUBMINER_WHISPER_MODEL` | Override legacy `youtubeSubgen.whisperModel` fallback compatibility path |
|
||||||
| `SUBMINER_WHISPER_VAD_MODEL` | Override `youtubeSubgen.whisperVadModel` for launcher |
|
| `SUBMINER_WHISPER_VAD_MODEL` | Override legacy `youtubeSubgen.whisperVadModel` fallback compatibility path |
|
||||||
| `SUBMINER_WHISPER_THREADS` | Override `youtubeSubgen.whisperThreads` for launcher |
|
| `SUBMINER_WHISPER_THREADS` | Override legacy `youtubeSubgen.whisperThreads` fallback compatibility value |
|
||||||
| `SUBMINER_YT_SUBGEN_OUT_DIR` | Override generated subtitle output directory |
|
| `SUBMINER_YT_SUBGEN_OUT_DIR` | Override legacy fallback subtitle output directory |
|
||||||
| `SUBMINER_YT_SUBGEN_AUDIO_FORMAT` | Override extraction format used for whisper fallback |
|
| `SUBMINER_YT_SUBGEN_AUDIO_FORMAT` | Override extraction format used by legacy fallback subtitle path |
|
||||||
| `SUBMINER_YT_SUBGEN_KEEP_TEMP` | Set to `1` to keep temporary subtitle-generation workspace |
|
| `SUBMINER_YT_SUBGEN_KEEP_TEMP` | Set to `1` to keep legacy fallback subtitle workspace |
|
||||||
| `SUBMINER_JIMAKU_API_KEY` | Override Jimaku API key for launcher subtitle downloads |
|
| `SUBMINER_JIMAKU_API_KEY` | Override Jimaku API key for launcher subtitle downloads |
|
||||||
| `SUBMINER_JIMAKU_API_KEY_COMMAND` | Command used to resolve Jimaku API key at runtime |
|
| `SUBMINER_JIMAKU_API_KEY_COMMAND` | Command used to resolve Jimaku API key at runtime |
|
||||||
| `SUBMINER_JIMAKU_API_BASE_URL` | Override Jimaku API base URL |
|
| `SUBMINER_JIMAKU_API_BASE_URL` | Override Jimaku API base URL |
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ features:
|
|||||||
- icon:
|
- icon:
|
||||||
src: /assets/video.svg
|
src: /assets/video.svg
|
||||||
alt: Video playback icon
|
alt: Video playback icon
|
||||||
title: YouTube & Whisper
|
title: YouTube Playback
|
||||||
details: Play YouTube URLs or searches with native subtitles, or generate them with whisper.cpp and optional AI cleanup.
|
details: Play YouTube URLs or searches with native subtitles and auto-loaded tracks.
|
||||||
link: /usage#youtube-playback
|
link: /usage#youtube-playback
|
||||||
linkText: YouTube playback
|
linkText: YouTube playback
|
||||||
- icon:
|
- icon:
|
||||||
|
|||||||
@@ -66,7 +66,6 @@ subminer --setup # Open first-run setup popup
|
|||||||
| Subcommand | Purpose |
|
| Subcommand | Purpose |
|
||||||
| -------------------------- | ---------------------------------------------------------- |
|
| -------------------------- | ---------------------------------------------------------- |
|
||||||
| `subminer jellyfin` / `jf` | Jellyfin workflows (`-d` discovery, `-p` play, `-l` login) |
|
| `subminer jellyfin` / `jf` | Jellyfin workflows (`-d` discovery, `-p` play, `-l` login) |
|
||||||
| `subminer yt` / `youtube` | YouTube shorthand (`-o`, `-m`) |
|
|
||||||
| `subminer doctor` | Dependency + config + socket diagnostics |
|
| `subminer doctor` | Dependency + config + socket diagnostics |
|
||||||
| `subminer config path` | Print active config file path |
|
| `subminer config path` | Print active config file path |
|
||||||
| `subminer config show` | Print active config contents |
|
| `subminer config show` | Print active config contents |
|
||||||
|
|||||||
@@ -187,7 +187,7 @@
|
|||||||
// ==========================================
|
// ==========================================
|
||||||
// Secondary Subtitles
|
// Secondary Subtitles
|
||||||
// Dual subtitle track options.
|
// Dual subtitle track options.
|
||||||
// Used by subminer YouTube subtitle generation as secondary language preferences.
|
// Used by the YouTube subtitle loading flow as secondary language preferences.
|
||||||
// Hot-reload: defaultMode updates live while SubMiner is running.
|
// Hot-reload: defaultMode updates live while SubMiner is running.
|
||||||
// ==========================================
|
// ==========================================
|
||||||
"secondarySub": {
|
"secondarySub": {
|
||||||
@@ -414,24 +414,24 @@
|
|||||||
}, // Jimaku API configuration and defaults.
|
}, // Jimaku API configuration and defaults.
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// YouTube Subtitle Generation
|
// YouTube Playback Settings
|
||||||
// Defaults for SubMiner YouTube subtitle generation.
|
// Defaults for SubMiner YouTube subtitle loading and languages.
|
||||||
// ==========================================
|
// ==========================================
|
||||||
"youtubeSubgen": {
|
"youtubeSubgen": {
|
||||||
"whisperBin": "", // Path to whisper.cpp CLI used as fallback transcription engine.
|
"whisperBin": "", // Legacy compatibility path kept for external subtitle fallback tools; not used by default.
|
||||||
"whisperModel": "", // Path to whisper model used for fallback transcription.
|
"whisperModel": "", // Legacy compatibility model path kept for external subtitle fallback tooling; not used by default.
|
||||||
"whisperVadModel": "", // Path to optional whisper VAD model used for subtitle generation.
|
"whisperVadModel": "", // Legacy compatibility VAD path kept for external subtitle fallback tooling; not used by default.
|
||||||
"whisperThreads": 4, // Thread count passed to whisper.cpp subtitle generation runs.
|
"whisperThreads": 4, // Legacy thread tuning for subtitle fallback tooling; not used by default.
|
||||||
"fixWithAi": false, // Use shared AI provider to post-process whisper-generated YouTube subtitles. Values: true | false
|
"fixWithAi": false, // Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default. Values: true | false
|
||||||
"ai": {
|
"ai": {
|
||||||
"model": "", // Optional model override for YouTube subtitle AI post-processing.
|
"model": "", // Optional model override for legacy subtitle fallback post-processing; not used by default.
|
||||||
"systemPrompt": "" // Optional system prompt override for YouTube subtitle AI post-processing.
|
"systemPrompt": "" // Optional system prompt override for legacy subtitle fallback post-processing; not used by default.
|
||||||
}, // Ai setting.
|
}, // Ai setting.
|
||||||
"primarySubLanguages": [
|
"primarySubLanguages": [
|
||||||
"ja",
|
"ja",
|
||||||
"jpn"
|
"jpn"
|
||||||
] // Comma-separated primary subtitle language priority used by the launcher.
|
] // Comma-separated primary subtitle language priority used by the launcher.
|
||||||
}, // Defaults for SubMiner YouTube subtitle generation.
|
}, // Defaults for SubMiner YouTube subtitle loading and languages.
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// Anilist
|
// Anilist
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ Mouse-hover playback behavior is configured separately from shortcuts: `subtitle
|
|||||||
| `Ctrl/Cmd+Shift+V` | Cycle secondary subtitle mode (hidden → visible → hover) | `shortcuts.toggleSecondarySub` |
|
| `Ctrl/Cmd+Shift+V` | Cycle secondary subtitle mode (hidden → visible → hover) | `shortcuts.toggleSecondarySub` |
|
||||||
| `Ctrl/Cmd+Shift+O` | Open runtime options palette | `shortcuts.openRuntimeOptions` |
|
| `Ctrl/Cmd+Shift+O` | Open runtime options palette | `shortcuts.openRuntimeOptions` |
|
||||||
| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` |
|
| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` |
|
||||||
|
| `Ctrl+Alt+C` | Open the manual YouTube subtitle picker | `keybindings` |
|
||||||
| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` |
|
| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` |
|
||||||
| `\` | Toggle subtitle sidebar | `subtitleSidebar.toggleKey` |
|
| `\` | Toggle subtitle sidebar | `subtitleSidebar.toggleKey` |
|
||||||
| `` ` `` | Toggle stats overlay | `stats.toggleKey` |
|
| `` ` `` | Toggle stats overlay | `stats.toggleKey` |
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ SubMiner retries the connection automatically with increasing delays (200 ms, 50
|
|||||||
- Common spikes come from:
|
- Common spikes come from:
|
||||||
- first subtitle parse/tokenization bursts
|
- first subtitle parse/tokenization bursts
|
||||||
- media generation (`ffmpeg` audio/image and AVIF paths)
|
- media generation (`ffmpeg` audio/image and AVIF paths)
|
||||||
- media sync and subtitle tooling (`alass`, `ffsubsync`, `whisper` fallback path)
|
- media sync and subtitle tooling (`alass`, `ffsubsync`)
|
||||||
- `ankiConnect` enrichment (plus polling overhead when proxy mode is disabled)
|
- `ankiConnect` enrichment (plus polling overhead when proxy mode is disabled)
|
||||||
|
|
||||||
### If playback feels sluggish
|
### If playback feels sluggish
|
||||||
@@ -57,7 +57,7 @@ SubMiner retries the connection automatically with increasing delays (200 ms, 50
|
|||||||
|
|
||||||
- disable AI translation when not needed (`ankiConnect.ai.enabled: false`)
|
- disable AI translation when not needed (`ankiConnect.ai.enabled: false`)
|
||||||
- if needed, run immersion telemetry with lower duration expectations (`immersionTracking.enabled: false` for constrained sessions)
|
- if needed, run immersion telemetry with lower duration expectations (`immersionTracking.enabled: false` for constrained sessions)
|
||||||
- prefer YouTube `--mode automatic` over `preprocess` on low-resource systems
|
- favor the default lightweight YouTube subtitle startup settings on low-resource systems
|
||||||
|
|
||||||
### Practical low-impact profile
|
### Practical low-impact profile
|
||||||
|
|
||||||
|
|||||||
@@ -78,8 +78,6 @@ subminer mpv idle # Launch detached idle mpv with SubMiner defau
|
|||||||
subminer dictionary /path/to/file-or-directory # Generate character dictionary ZIP from target (manual Yomitan import)
|
subminer dictionary /path/to/file-or-directory # Generate character dictionary ZIP from target (manual Yomitan import)
|
||||||
subminer texthooker # Launch texthooker-only mode
|
subminer texthooker # Launch texthooker-only mode
|
||||||
subminer app --anilist # Pass args directly to SubMiner binary (example: AniList login flow)
|
subminer app --anilist # Pass args directly to SubMiner binary (example: AniList login flow)
|
||||||
subminer yt -o ~/subs https://youtu.be/... # YouTube subcommand: output directory shortcut
|
|
||||||
subminer yt --keep-temp --whisper-bin /path/to/whisper-cli --whisper-model /path/to/model.bin --whisper-vad-model /path/to/ggml-vad.bin https://youtu.be/... # Keep generated subtitle workspace for debugging
|
|
||||||
|
|
||||||
# Direct packaged app control
|
# Direct packaged app control
|
||||||
SubMiner.AppImage --background # Start in background (tray + IPC wait, minimal logs)
|
SubMiner.AppImage --background # Start in background (tray + IPC wait, minimal logs)
|
||||||
@@ -137,14 +135,13 @@ This flow requires `mpv.exe` to be on `PATH`. If it is installed elsewhere, set
|
|||||||
### Launcher Subcommands
|
### Launcher Subcommands
|
||||||
|
|
||||||
- `subminer jellyfin` / `subminer jf`: Jellyfin-focused workflow aliases.
|
- `subminer jellyfin` / `subminer jf`: Jellyfin-focused workflow aliases.
|
||||||
- `subminer yt` / `subminer youtube`: YouTube-focused shorthand flags (`-o`, `--keep-temp`, `--whisper-*`).
|
|
||||||
- `subminer doctor`: health checks for core dependencies and runtime paths.
|
- `subminer doctor`: health checks for core dependencies and runtime paths.
|
||||||
- `subminer config`: config helpers (`path`, `show`).
|
- `subminer config`: config helpers (`path`, `show`).
|
||||||
- `subminer mpv`: mpv helpers (`status`, `socket`, `idle`).
|
- `subminer mpv`: mpv helpers (`status`, `socket`, `idle`).
|
||||||
- `subminer dictionary <path>`: generates a Yomitan-importable character dictionary ZIP from a file/directory target.
|
- `subminer dictionary <path>`: generates a Yomitan-importable character dictionary ZIP from a file/directory target.
|
||||||
- `subminer texthooker`: texthooker-only shortcut (same behavior as `--texthooker`).
|
- `subminer texthooker`: texthooker-only shortcut (same behavior as `--texthooker`).
|
||||||
- `subminer app` / `subminer bin`: direct passthrough to the SubMiner binary/AppImage.
|
- `subminer app` / `subminer bin`: direct passthrough to the SubMiner binary/AppImage.
|
||||||
- Subcommand help pages are available (for example `subminer jellyfin -h`, `subminer yt -h`).
|
- Subcommand help pages are available (for example `subminer jellyfin -h`).
|
||||||
|
|
||||||
### First-Run Setup
|
### First-Run Setup
|
||||||
|
|
||||||
@@ -174,8 +171,8 @@ AniList character dictionary auto-sync (optional):
|
|||||||
- SubMiner syncs the currently watched AniList media into a per-media snapshot, then rebuilds one merged `SubMiner Character Dictionary` from the most recently used snapshots.
|
- SubMiner syncs the currently watched AniList media into a per-media snapshot, then rebuilds one merged `SubMiner Character Dictionary` from the most recently used snapshots.
|
||||||
- Rotation limit defaults to 3 recent media snapshots in that merged dictionary (`maxLoaded`).
|
- Rotation limit defaults to 3 recent media snapshots in that merged dictionary (`maxLoaded`).
|
||||||
|
|
||||||
Use subcommands for Jellyfin/YouTube command families (`subminer jellyfin ...`, `subminer yt ...`).
|
Use subcommands for Jellyfin workflows (`subminer jellyfin ...`).
|
||||||
Top-level launcher flags like `--jellyfin-*` and `--yt-subgen-*` are intentionally rejected.
|
Top-level launcher flags like `--jellyfin-*` are intentionally rejected.
|
||||||
|
|
||||||
### MPV Profile Example (mpv.conf)
|
### MPV Profile Example (mpv.conf)
|
||||||
|
|
||||||
@@ -228,28 +225,17 @@ If you also use Yomitan in a browser, configure that browser profile separately;
|
|||||||
### YouTube Playback
|
### YouTube Playback
|
||||||
|
|
||||||
`subminer` accepts direct URLs (for example, YouTube links) and `ytsearch:` targets.
|
`subminer` accepts direct URLs (for example, YouTube links) and `ytsearch:` targets.
|
||||||
For YouTube playback, SubMiner now resolves its default startup subtitle selection before mpv starts regular playback: it pauses at startup, auto-selects the default primary subtitle track plus a best-effort secondary track, then resumes with any downloaded subtitle files attached. Playback waits only for the primary subtitle to load and tokenize. If the primary subtitle cannot be loaded, playback resumes and SubMiner reports the failure through the configured notification path.
|
For YouTube playback, SubMiner resolves subtitle selection before mpv starts regular playback: it pauses at startup, auto-selects the default primary subtitle track plus a best-effort secondary track, then resumes when primary subtitles are ready.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- Install `yt-dlp` so mpv can resolve YouTube streams and subtitle tracks reliably.
|
- Install `yt-dlp` so mpv can resolve YouTube streams and subtitle tracks reliably.
|
||||||
- For YouTube URLs, startup no longer requires the overlay picker.
|
- For YouTube URLs, startup no longer requires opening the picker first; SubMiner loads subtitles and keeps the overlay available for retries.
|
||||||
- Press `Ctrl+Shift+J` during active YouTube playback to open the manual YouTube subtitle picker and retry track selection.
|
- Press `Ctrl+Alt+C` during active YouTube playback to open the manual YouTube subtitle picker and retry track selection.
|
||||||
- For YouTube URLs, `subminer` generates only the missing tracks after probing YouTube's native/manual subtitle inventory.
|
- For YouTube URLs, `subminer` probes available YouTube/manual subtitle tracks and loads matching tracks in mpv.
|
||||||
- It probes manual/native YouTube subtitle tracks first, then falls back to local `whisper.cpp` only for missing tracks.
|
|
||||||
- Primary subtitle target languages come from `youtubeSubgen.primarySubLanguages` (defaults to `["ja","jpn"]`).
|
- Primary subtitle target languages come from `youtubeSubgen.primarySubLanguages` (defaults to `["ja","jpn"]`).
|
||||||
- Secondary target languages come from `secondarySub.secondarySubLanguages` (defaults to English if unset).
|
- Secondary target languages come from `secondarySub.secondarySubLanguages` (defaults to English if unset).
|
||||||
- Whisper translation fallback currently only supports English secondary targets; non-English secondary targets rely on native/manual subtitle availability.
|
- Configure defaults in `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc`) under `youtubeSubgen` and `secondarySub`.
|
||||||
- Optional AI cleanup for whisper-generated subtitles is controlled by `youtubeSubgen.fixWithAi` plus the shared top-level `ai` config (with optional `youtubeSubgen.ai` overrides).
|
|
||||||
- Configure defaults in `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc`) under `youtubeSubgen`, `secondarySub`, and `ai`.
|
|
||||||
- CLI overrides are available through `subminer yt` / `subminer youtube`:
|
|
||||||
- `-o, --out-dir`
|
|
||||||
- `--keep-temp`
|
|
||||||
- `--whisper-bin`
|
|
||||||
- `--whisper-model`
|
|
||||||
- `--whisper-vad-model`
|
|
||||||
- `--whisper-threads`
|
|
||||||
- `--yt-subgen-audio-format`
|
|
||||||
|
|
||||||
## Controller Support
|
## Controller Support
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export function runDoctorCommand(
|
|||||||
ok: deps.commandExists('ffmpeg'),
|
ok: deps.commandExists('ffmpeg'),
|
||||||
detail: deps.commandExists('ffmpeg')
|
detail: deps.commandExists('ffmpeg')
|
||||||
? 'found'
|
? 'found'
|
||||||
: 'missing (optional unless subtitle generation)',
|
: 'missing (optional unless legacy subtitle fallback is enabled)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'fzf',
|
label: 'fzf',
|
||||||
|
|||||||
@@ -1735,7 +1735,7 @@ test('accepts top-level ai config', () => {
|
|||||||
assert.equal(config.ai.requestTimeoutMs, 20000);
|
assert.equal(config.ai.requestTimeoutMs, 20000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('accepts per-feature ai overrides for anki and youtube subtitle generation', () => {
|
test('accepts per-feature ai overrides for anki and YouTube subtitles', () => {
|
||||||
const dir = makeTempDir();
|
const dir = makeTempDir();
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.join(dir, 'config.jsonc'),
|
path.join(dir, 'config.jsonc'),
|
||||||
@@ -2074,16 +2074,16 @@ test('template generator includes known keys', () => {
|
|||||||
);
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
output,
|
output,
|
||||||
/"fixWithAi": false,? \/\/ Use shared AI provider to post-process whisper-generated YouTube subtitles\. Values: true \| false/,
|
/"fixWithAi": false,? \/\/ Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default\. Values: true \| false/,
|
||||||
);
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
output,
|
output,
|
||||||
/"systemPrompt": "",? \/\/ Optional system prompt override for YouTube subtitle AI post-processing\./,
|
/"systemPrompt": "",? \/\/ Optional system prompt override for legacy subtitle fallback post-processing; not used by default\./,
|
||||||
);
|
);
|
||||||
assert.doesNotMatch(output, /"mode": "automatic"/);
|
assert.doesNotMatch(output, /"mode": "automatic"/);
|
||||||
assert.match(
|
assert.match(
|
||||||
output,
|
output,
|
||||||
/"whisperThreads": 4,? \/\/ Thread count passed to whisper\.cpp subtitle generation runs\./,
|
/"whisperThreads": 4,? \/\/ Legacy thread tuning for subtitle fallback tooling; not used by default\./,
|
||||||
);
|
);
|
||||||
assert.match(
|
assert.match(
|
||||||
output,
|
output,
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ test('default keybindings include primary and secondary subtitle track cycling o
|
|||||||
);
|
);
|
||||||
assert.deepEqual(keybindingMap.get('KeyJ'), ['cycle', 'sid']);
|
assert.deepEqual(keybindingMap.get('KeyJ'), ['cycle', 'sid']);
|
||||||
assert.deepEqual(keybindingMap.get('Shift+KeyJ'), ['cycle', 'secondary-sid']);
|
assert.deepEqual(keybindingMap.get('Shift+KeyJ'), ['cycle', 'secondary-sid']);
|
||||||
assert.deepEqual(keybindingMap.get('Ctrl+Shift+KeyJ'), ['__youtube-picker-open']);
|
assert.deepEqual(keybindingMap.get('Ctrl+Alt+KeyC'), ['__youtube-picker-open']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('default keybindings include fullscreen on F', () => {
|
test('default keybindings include fullscreen on F', () => {
|
||||||
|
|||||||
@@ -369,43 +369,47 @@ export function buildIntegrationConfigOptionRegistry(
|
|||||||
path: 'youtubeSubgen.whisperBin',
|
path: 'youtubeSubgen.whisperBin',
|
||||||
kind: 'string',
|
kind: 'string',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.whisperBin,
|
defaultValue: defaultConfig.youtubeSubgen.whisperBin,
|
||||||
description: 'Path to whisper.cpp CLI used as fallback transcription engine.',
|
description: 'Legacy compatibility path kept for external subtitle fallback tools; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.whisperModel',
|
path: 'youtubeSubgen.whisperModel',
|
||||||
kind: 'string',
|
kind: 'string',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.whisperModel,
|
defaultValue: defaultConfig.youtubeSubgen.whisperModel,
|
||||||
description: 'Path to whisper model used for fallback transcription.',
|
description: 'Legacy compatibility model path kept for external subtitle fallback tooling; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.whisperVadModel',
|
path: 'youtubeSubgen.whisperVadModel',
|
||||||
kind: 'string',
|
kind: 'string',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.whisperVadModel,
|
defaultValue: defaultConfig.youtubeSubgen.whisperVadModel,
|
||||||
description: 'Path to optional whisper VAD model used for subtitle generation.',
|
description:
|
||||||
|
'Legacy compatibility VAD path kept for external subtitle fallback tooling; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.whisperThreads',
|
path: 'youtubeSubgen.whisperThreads',
|
||||||
kind: 'number',
|
kind: 'number',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.whisperThreads,
|
defaultValue: defaultConfig.youtubeSubgen.whisperThreads,
|
||||||
description: 'Thread count passed to whisper.cpp subtitle generation runs.',
|
description: 'Legacy thread tuning for subtitle fallback tooling; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.fixWithAi',
|
path: 'youtubeSubgen.fixWithAi',
|
||||||
kind: 'boolean',
|
kind: 'boolean',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.fixWithAi,
|
defaultValue: defaultConfig.youtubeSubgen.fixWithAi,
|
||||||
description: 'Use shared AI provider to post-process whisper-generated YouTube subtitles.',
|
description:
|
||||||
|
'Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.ai.model',
|
path: 'youtubeSubgen.ai.model',
|
||||||
kind: 'string',
|
kind: 'string',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.ai.model,
|
defaultValue: defaultConfig.youtubeSubgen.ai.model,
|
||||||
description: 'Optional model override for YouTube subtitle AI post-processing.',
|
description:
|
||||||
|
'Optional model override for legacy subtitle fallback post-processing; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.ai.systemPrompt',
|
path: 'youtubeSubgen.ai.systemPrompt',
|
||||||
kind: 'string',
|
kind: 'string',
|
||||||
defaultValue: defaultConfig.youtubeSubgen.ai.systemPrompt,
|
defaultValue: defaultConfig.youtubeSubgen.ai.systemPrompt,
|
||||||
description: 'Optional system prompt override for YouTube subtitle AI post-processing.',
|
description:
|
||||||
|
'Optional system prompt override for legacy subtitle fallback post-processing; not used by default.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'youtubeSubgen.primarySubLanguages',
|
path: 'youtubeSubgen.primarySubLanguages',
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ export const DEFAULT_KEYBINDINGS: NonNullable<ResolvedConfig['keybindings']> = [
|
|||||||
key: 'Shift+BracketLeft',
|
key: 'Shift+BracketLeft',
|
||||||
command: [SPECIAL_COMMANDS.SHIFT_SUB_DELAY_TO_PREVIOUS_SUBTITLE_START],
|
command: [SPECIAL_COMMANDS.SHIFT_SUB_DELAY_TO_PREVIOUS_SUBTITLE_START],
|
||||||
},
|
},
|
||||||
{ key: 'Ctrl+Shift+KeyJ', command: [SPECIAL_COMMANDS.YOUTUBE_PICKER_OPEN] },
|
{ key: 'Ctrl+Alt+KeyC', command: [SPECIAL_COMMANDS.YOUTUBE_PICKER_OPEN] },
|
||||||
{ key: 'Ctrl+Shift+KeyH', command: [SPECIAL_COMMANDS.REPLAY_SUBTITLE] },
|
{ key: 'Ctrl+Shift+KeyH', command: [SPECIAL_COMMANDS.REPLAY_SUBTITLE] },
|
||||||
{ key: 'Ctrl+Shift+KeyL', command: [SPECIAL_COMMANDS.PLAY_NEXT_SUBTITLE] },
|
{ key: 'Ctrl+Shift+KeyL', command: [SPECIAL_COMMANDS.PLAY_NEXT_SUBTITLE] },
|
||||||
{ key: 'KeyQ', command: ['quit'] },
|
{ key: 'KeyQ', command: ['quit'] },
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const CORE_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
|
|||||||
title: 'Secondary Subtitles',
|
title: 'Secondary Subtitles',
|
||||||
description: [
|
description: [
|
||||||
'Dual subtitle track options.',
|
'Dual subtitle track options.',
|
||||||
'Used by subminer YouTube subtitle generation as secondary language preferences.',
|
'Used by the YouTube subtitle loading flow as secondary language preferences.',
|
||||||
],
|
],
|
||||||
notes: ['Hot-reload: defaultMode updates live while SubMiner is running.'],
|
notes: ['Hot-reload: defaultMode updates live while SubMiner is running.'],
|
||||||
key: 'secondarySub',
|
key: 'secondarySub',
|
||||||
@@ -130,8 +130,8 @@ const INTEGRATION_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
|
|||||||
key: 'jimaku',
|
key: 'jimaku',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'YouTube Subtitle Generation',
|
title: 'YouTube Playback Settings',
|
||||||
description: ['Defaults for SubMiner YouTube subtitle generation.'],
|
description: ['Defaults for SubMiner YouTube subtitle loading and languages.'],
|
||||||
key: 'youtubeSubgen',
|
key: 'youtubeSubgen',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user