mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-02 06:22:42 -08:00
docs: remove obsolete subtitle position edit mode references
This commit is contained in:
@@ -72,27 +72,466 @@ Restart-required changes:
|
|||||||
|
|
||||||
The configuration file includes several main sections:
|
The configuration file includes several main sections:
|
||||||
|
|
||||||
- [**AnkiConnect**](#ankiconnect) - Automatic Anki card creation with media
|
**Core Settings**
|
||||||
|
|
||||||
|
- [**Logging**](#logging) - Runtime log level
|
||||||
- [**Auto-Start Overlay**](#auto-start-overlay) - Automatically show overlay on MPV connection
|
- [**Auto-Start Overlay**](#auto-start-overlay) - Automatically show overlay on MPV connection
|
||||||
- [**Visible Overlay Subtitle Binding**](#visible-overlay-subtitle-binding) - Link visible overlay toggles to MPV subtitle visibility
|
- [**Startup Warmups**](#startup-warmups) - Control what preloads on startup vs first-use defer
|
||||||
- [**Auto Subtitle Sync**](#auto-subtitle-sync) - Sync current subtitle with `alass`/`ffsubsync`
|
- [**WebSocket Server**](#websocket-server) - Built-in subtitle broadcasting server
|
||||||
- [**Subtitle Position Edit**](#subtitle-position-edit) - Fine-tune subtitle alignment in overlay
|
- [**Texthooker**](#texthooker) - Control browser opening behavior
|
||||||
|
|
||||||
|
**Subtitle Display**
|
||||||
|
|
||||||
|
- [**Subtitle Style**](#subtitle-style) - Appearance customization
|
||||||
|
- [**Subtitle Position**](#subtitle-position) - Overlay vertical positioning
|
||||||
|
- [**Secondary Subtitles**](#secondary-subtitles) - Dual subtitle track support
|
||||||
|
|
||||||
|
**Keyboard & Controls**
|
||||||
|
|
||||||
|
- [**Keybindings**](#keybindings) - MPV command shortcuts
|
||||||
|
- [**Shortcuts Configuration**](#shortcuts-configuration) - Overlay keyboard shortcuts
|
||||||
|
- [**Manual Card Update Shortcuts**](#manual-card-update-shortcuts) - Shortcuts for manual Anki card workflows
|
||||||
|
- [**Session Help Modal**](#session-help-modal) - In-overlay shortcut reference
|
||||||
|
- [**Runtime Option Palette**](#runtime-option-palette) - Live, session-only option toggles
|
||||||
|
|
||||||
|
**Anki Integration**
|
||||||
|
|
||||||
|
- [**AnkiConnect**](#ankiconnect) - Automatic Anki card creation with media
|
||||||
|
- [**N+1 Word Highlighting**](#n1-word-highlighting) - Known-word cache and single-target highlighting
|
||||||
|
- [**Field Grouping Modes**](#field-grouping-modes) - Kiku/Lapis duplicate card merging
|
||||||
|
|
||||||
|
**External Integrations**
|
||||||
|
|
||||||
- [**Jimaku**](#jimaku) - Jimaku API configuration and defaults
|
- [**Jimaku**](#jimaku) - Jimaku API configuration and defaults
|
||||||
|
- [**Auto Subtitle Sync**](#auto-subtitle-sync) - Sync current subtitle with `alass`/`ffsubsync`
|
||||||
- [**AniList**](#anilist) - Optional post-watch progress updates
|
- [**AniList**](#anilist) - Optional post-watch progress updates
|
||||||
- [**Jellyfin**](#jellyfin) - Optional Jellyfin auth, library listing, and playback launch
|
- [**Jellyfin**](#jellyfin) - Optional Jellyfin auth, library listing, and playback launch
|
||||||
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
- [**Discord Rich Presence**](#discord-rich-presence) - Optional Discord activity card updates
|
||||||
- [**Keybindings**](#keybindings) - MPV command shortcuts
|
|
||||||
- [**Runtime Option Palette**](#runtime-option-palette) - Live, session-only option toggles
|
|
||||||
- [**Secondary Subtitles**](#secondary-subtitles) - Dual subtitle track support
|
|
||||||
- [**Shortcuts Configuration**](#shortcuts-configuration) - Overlay keyboard shortcuts
|
|
||||||
- [**Subtitle Position**](#subtitle-position) - Overlay vertical positioning
|
|
||||||
- [**Subtitle Style**](#subtitle-style) - Appearance customization
|
|
||||||
- [**Texthooker**](#texthooker) - Control browser opening behavior
|
|
||||||
- [**WebSocket Server**](#websocket-server) - Built-in subtitle broadcasting server
|
|
||||||
- [**Startup Warmups**](#startup-warmups) - Control what preloads on startup vs first-use defer
|
|
||||||
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
- [**Immersion Tracking**](#immersion-tracking) - Track subtitle sessions and mining activity in SQLite
|
||||||
- [**YouTube Subtitle Generation**](#youtube-subtitle-generation) - Launcher defaults for yt-dlp + local whisper fallback
|
- [**YouTube Subtitle Generation**](#youtube-subtitle-generation) - Launcher defaults for yt-dlp + local whisper fallback
|
||||||
|
|
||||||
|
## Core Settings
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
Control the minimum log level for runtime output:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"logging": {
|
||||||
|
"level": "info"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ------- | ----------------------------------- | ------------------------------------------------ |
|
||||||
|
| `level` | `"debug"`, `"info"`, `"warn"`, `"error"` | Minimum log level for runtime logging (default: `"info"`) |
|
||||||
|
|
||||||
|
### Auto-Start Overlay
|
||||||
|
|
||||||
|
Control whether the overlay automatically becomes visible when it connects to mpv:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"auto_start_overlay": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| -------------------- | --------------- | ------------------------------------------------------ |
|
||||||
|
| `auto_start_overlay` | `true`, `false` | Auto-show overlay on mpv connection (default: `false`) |
|
||||||
|
|
||||||
|
The mpv plugin controls startup overlay visibility via `auto_start_visible_overlay` in `subminer.conf`.
|
||||||
|
For wrapper-driven playback, `subminer.conf` can also enable startup pause gating with
|
||||||
|
`auto_start_pause_until_ready` (requires `auto_start=yes` + `auto_start_visible_overlay=yes`).
|
||||||
|
Current plugin defaults in `subminer.conf` are:
|
||||||
|
|
||||||
|
- `auto_start=yes`
|
||||||
|
- `auto_start_visible_overlay=yes`
|
||||||
|
- `auto_start_pause_until_ready=yes`
|
||||||
|
|
||||||
|
### Startup Warmups
|
||||||
|
|
||||||
|
Control which startup warmups run in the background versus deferring to first real usage:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"startupWarmups": {
|
||||||
|
"lowPowerMode": false,
|
||||||
|
"mecab": true,
|
||||||
|
"yomitanExtension": true,
|
||||||
|
"subtitleDictionaries": true,
|
||||||
|
"jellyfinRemoteSession": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------- |
|
||||||
|
| `lowPowerMode` | `true`, `false` | Defer all warmups except Yomitan extension |
|
||||||
|
| `mecab` | `true`, `false` | Warm up MeCab tokenizer at startup |
|
||||||
|
| `yomitanExtension` | `true`, `false` | Warm up Yomitan extension at startup |
|
||||||
|
| `subtitleDictionaries` | `true`, `false` | Warm up JLPT + frequency dictionaries at startup |
|
||||||
|
| `jellyfinRemoteSession` | `true`, `false` | Warm up Jellyfin remote session at startup (still requires Jellyfin remote auto-connect settings) |
|
||||||
|
|
||||||
|
Defaults warm everything (`true` for all toggles, `lowPowerMode: false`). Setting a warmup toggle to `false` defers that work until first usage.
|
||||||
|
|
||||||
|
### WebSocket Server
|
||||||
|
|
||||||
|
The overlay includes a built-in WebSocket server that broadcasts subtitle text to connected clients (such as texthooker-ui) for external processing.
|
||||||
|
|
||||||
|
By default, the server uses "auto" mode: it starts automatically unless [mpv_websocket](https://github.com/kuroahna/mpv_websocket) is detected at `~/.config/mpv/mpv_websocket`. If you have mpv_websocket installed, the built-in server is skipped to avoid conflicts.
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"websocket": {
|
||||||
|
"enabled": "auto",
|
||||||
|
"port": 6677
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| --------- | ------------------------- | -------------------------------------------------------- |
|
||||||
|
| `enabled` | `true`, `false`, `"auto"` | `"auto"` (default) disables if mpv_websocket is detected |
|
||||||
|
| `port` | number | WebSocket server port (default: 6677) |
|
||||||
|
|
||||||
|
### Texthooker
|
||||||
|
|
||||||
|
Control whether the browser opens automatically when texthooker starts:
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"texthooker": {
|
||||||
|
"openBrowser": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Subtitle Display
|
||||||
|
|
||||||
|
### Subtitle Style
|
||||||
|
|
||||||
|
Customize the appearance of primary and secondary subtitles:
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subtitleStyle": {
|
||||||
|
"fontFamily": "M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP",
|
||||||
|
"fontSize": 35,
|
||||||
|
"fontColor": "#cad3f5",
|
||||||
|
"fontWeight": "600",
|
||||||
|
"lineHeight": 1.35,
|
||||||
|
"letterSpacing": "-0.01em",
|
||||||
|
"wordSpacing": 0,
|
||||||
|
"fontKerning": "normal",
|
||||||
|
"textRendering": "geometricPrecision",
|
||||||
|
"textShadow": "0 3px 10px rgba(0,0,0,0.69)",
|
||||||
|
"fontStyle": "normal",
|
||||||
|
"backgroundColor": "rgb(30, 32, 48, 0.88)",
|
||||||
|
"backdropFilter": "blur(6px)",
|
||||||
|
"secondary": {
|
||||||
|
"fontFamily": "Inter, Noto Sans, Helvetica Neue, sans-serif",
|
||||||
|
"fontSize": 24,
|
||||||
|
"fontColor": "#cad3f5",
|
||||||
|
"backgroundColor": "transparent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ---------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `fontFamily` | string | CSS font-family value (default: `"M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP"`) |
|
||||||
|
| `fontSize` | number (px) | Font size in pixels (default: `35`) |
|
||||||
|
| `fontColor` | string | Any CSS color value (default: `"#cad3f5"`) |
|
||||||
|
| `fontWeight` | string | CSS font-weight, e.g. `"bold"`, `"normal"`, `"600"` (default: `"600"`) |
|
||||||
|
| `fontStyle` | string | `"normal"` or `"italic"` (default: `"normal"`) |
|
||||||
|
| `backgroundColor` | string | Any CSS color, including `"transparent"` (default: `"rgb(30, 32, 48, 0.88)"`) |
|
||||||
|
| `enableJlpt` | boolean | Enable JLPT level underline styling (`false` by default) |
|
||||||
|
| `preserveLineBreaks` | boolean | Preserve line breaks in visible overlay subtitle rendering (`false` by default). Enable to mirror mpv line layout. |
|
||||||
|
| `autoPauseVideoOnHover` | boolean | Pause playback while mouse hovers subtitle text, then resume on leave (`true` by default). |
|
||||||
|
| `hoverTokenColor` | string | Hex color used for hovered subtitle token highlight in mpv (default: catppuccin mauve) |
|
||||||
|
| `hoverTokenBackgroundColor` | string | CSS color used for hovered subtitle token background highlight (default: semi-transparent dark) |
|
||||||
|
| `frequencyDictionary.enabled` | boolean | Enable frequency highlighting from dictionary lookups (`false` by default) |
|
||||||
|
| `frequencyDictionary.sourcePath` | string | Path to a local frequency dictionary root. Leave empty or omit to use installed/default frequency-dictionary search paths. |
|
||||||
|
| `frequencyDictionary.topX` | number | Only color tokens whose frequency rank is `<= topX` (`1000` by default) |
|
||||||
|
| `frequencyDictionary.mode` | string | `"single"` or `"banded"` (`"single"` by default) |
|
||||||
|
| `frequencyDictionary.matchMode` | string | `"headword"` or `"surface"` (`"headword"` by default) |
|
||||||
|
| `frequencyDictionary.singleColor` | string | Color used for all highlighted tokens in single mode |
|
||||||
|
| `frequencyDictionary.bandedColors` | string[] | Array of five hex colors used for ranked bands in banded mode |
|
||||||
|
| `nPlusOneColor` | string | Existing n+1 highlight color (default: `#c6a0f6`) |
|
||||||
|
| `knownWordColor` | string | Existing known-word highlight color (default: `#a6da95`) |
|
||||||
|
| `jlptColors` | object | JLPT level underline colors object (`N1`..`N5`) |
|
||||||
|
| `secondary` | object | Override any of the above for secondary subtitles (optional) |
|
||||||
|
|
||||||
|
JLPT underlining is powered by offline term-meta bank files at runtime. See [`docs/jlpt-vocab-bundle.md`](jlpt-vocab-bundle.md) for required files, source/version refresh steps, and deterministic fallback behavior.
|
||||||
|
|
||||||
|
Frequency dictionary highlighting uses the same dictionary file format as JLPT bundle lookups (`term_meta_bank_*.json` under discovered dictionary directories). A token is highlighted when it has a positive integer `frequencyRank` (lower is more common) and the rank is within `topX`.
|
||||||
|
|
||||||
|
Lookup behavior:
|
||||||
|
|
||||||
|
- Set `frequencyDictionary.sourcePath` to a directory containing `term_meta_bank_*.json` for a fully custom source.
|
||||||
|
- If `sourcePath` is missing or empty, SubMiner searches default install/runtime locations for `frequency-dictionary` directories (for example app resources, user data paths, and current working directory).
|
||||||
|
- In both cases, only terms with a valid `frequencyRank` are used; everything else falls back to no highlighting.
|
||||||
|
- `frequencyDictionary.matchMode` controls which token text is used for frequency lookups: `headword` (dictionary form) or `surface` (visible subtitle text).
|
||||||
|
- Frequency highlighting skips tokens that look like non-lexical SFX/interjection noise (for example kana reduplication or short kana endings like `っ`), even when dictionary ranks exist.
|
||||||
|
|
||||||
|
In `single` mode all highlights use `singleColor`; in `banded` mode tokens map to five ascending color bands from most common to least common inside the topX window.
|
||||||
|
|
||||||
|
Secondary subtitle defaults: `fontFamily: "Inter, Noto Sans, Helvetica Neue, sans-serif"`, `fontSize: 24`, `fontColor: "#cad3f5"`, `backgroundColor: "transparent"`. Any property not set in `secondary` falls back to the CSS defaults.
|
||||||
|
|
||||||
|
**See `config.example.jsonc`** for the complete list of subtitle style configuration options.
|
||||||
|
|
||||||
|
`jlptColors` keys are:
|
||||||
|
|
||||||
|
| Key | Default | Description |
|
||||||
|
| ---- | --------- | ----------------------- |
|
||||||
|
| `N1` | `#ed8796` | JLPT N1 underline color |
|
||||||
|
| `N2` | `#f5a97f` | JLPT N2 underline color |
|
||||||
|
| `N3` | `#f9e2af` | JLPT N3 underline color |
|
||||||
|
| `N4` | `#a6e3a1` | JLPT N4 underline color |
|
||||||
|
| `N5` | `#8aadf4` | JLPT N5 underline color |
|
||||||
|
|
||||||
|
**Image Quality Notes:**
|
||||||
|
|
||||||
|
- `imageQuality` affects JPG and WebP only; PNG is lossless and ignores this setting
|
||||||
|
- JPG quality is mapped to FFmpeg's scale (2-31, lower = better)
|
||||||
|
- WebP quality uses FFmpeg's native 0-100 scale
|
||||||
|
|
||||||
|
### Subtitle Position
|
||||||
|
|
||||||
|
Set the initial vertical subtitle position (measured from the bottom of the screen):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"subtitlePosition": {
|
||||||
|
"yPercent": 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ---------- | ---------------- | ---------------------------------------------------------------------- |
|
||||||
|
| `yPercent` | number (0 - 100) | Distance from the bottom as a percent of screen height (default: `10`) |
|
||||||
|
In the overlay, you can fine-tune subtitle position at runtime with `Right-click + drag` on subtitle text.
|
||||||
|
|
||||||
|
### Secondary Subtitles
|
||||||
|
|
||||||
|
Display a second subtitle track (e.g., English alongside Japanese) in the overlay:
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"secondarySub": {
|
||||||
|
"secondarySubLanguages": ["eng", "en"],
|
||||||
|
"autoLoadSecondarySub": true,
|
||||||
|
"defaultMode": "hover"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ----------------------- | ---------------------------------- | ------------------------------------------------------ |
|
||||||
|
| `secondarySubLanguages` | string[] | Language codes to auto-load (e.g., `["eng", "en"]`) |
|
||||||
|
| `autoLoadSecondarySub` | `true`, `false` | Auto-detect and load matching secondary subtitle track |
|
||||||
|
| `defaultMode` | `"hidden"`, `"visible"`, `"hover"` | Initial display mode (default: `"hover"`) |
|
||||||
|
|
||||||
|
**Display modes:**
|
||||||
|
|
||||||
|
- **hidden** — Secondary subtitles not shown
|
||||||
|
- **visible** — Always visible at top of overlay
|
||||||
|
- **hover** — Only visible when hovering over the subtitle area (default)
|
||||||
|
|
||||||
|
**See `config.example.jsonc`** for additional secondary subtitle configuration options.
|
||||||
|
|
||||||
|
## Keyboard & Controls
|
||||||
|
|
||||||
|
### Keybindings
|
||||||
|
|
||||||
|
Add a `keybindings` array to configure keyboard shortcuts that send commands to mpv:
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options and more examples.
|
||||||
|
|
||||||
|
**Default keybindings:**
|
||||||
|
|
||||||
|
| Key | Command | Description |
|
||||||
|
| ----------------- | ---------------------------- | ------------------------------------- |
|
||||||
|
| `Space` | `["cycle", "pause"]` | Toggle pause |
|
||||||
|
| `KeyJ` | `["cycle", "sid"]` | Cycle primary subtitle track |
|
||||||
|
| `Shift+KeyJ` | `["cycle", "secondary-sid"]` | Cycle secondary subtitle track |
|
||||||
|
| `ArrowRight` | `["seek", 5]` | Seek forward 5 seconds |
|
||||||
|
| `ArrowLeft` | `["seek", -5]` | Seek backward 5 seconds |
|
||||||
|
| `ArrowUp` | `["seek", 60]` | Seek forward 60 seconds |
|
||||||
|
| `ArrowDown` | `["seek", -60]` | Seek backward 60 seconds |
|
||||||
|
| `Shift+KeyH` | `["sub-seek", -1]` | Jump to previous subtitle |
|
||||||
|
| `Shift+KeyL` | `["sub-seek", 1]` | Jump to next subtitle |
|
||||||
|
| `Ctrl+Shift+KeyH` | `["__replay-subtitle"]` | Replay current subtitle, pause at end |
|
||||||
|
| `Ctrl+Shift+KeyL` | `["__play-next-subtitle"]` | Play next subtitle, pause at end |
|
||||||
|
| `KeyQ` | `["quit"]` | Quit mpv |
|
||||||
|
| `Ctrl+KeyW` | `["quit"]` | Quit mpv |
|
||||||
|
|
||||||
|
**Custom keybindings example:**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"keybindings": [
|
||||||
|
{ "key": "ArrowRight", "command": ["seek", 5] },
|
||||||
|
{ "key": "ArrowLeft", "command": ["seek", -5] },
|
||||||
|
{ "key": "Shift+ArrowRight", "command": ["seek", 30] },
|
||||||
|
{ "key": "KeyR", "command": ["script-binding", "immersive/auto-replay"] },
|
||||||
|
{ "key": "KeyA", "command": ["script-message", "ankiconnect-add-note"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key format:** Use `KeyboardEvent.code` values (`Space`, `ArrowRight`, `KeyR`, etc.) with optional modifiers (`Ctrl+`, `Alt+`, `Shift+`, `Meta+`).
|
||||||
|
|
||||||
|
**Disable a default binding:** Set command to `null`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "key": "Space", "command": null }
|
||||||
|
```
|
||||||
|
|
||||||
|
**Special commands:** Commands prefixed with `__` are handled internally by the overlay rather than sent to mpv. `__replay-subtitle` replays the current subtitle and pauses at its end. `__play-next-subtitle` seeks to the next subtitle, plays it, and pauses at its end. `__runtime-options-open` opens the runtime options palette. `__runtime-option-cycle:<id>[:next|prev]` cycles a runtime option value.
|
||||||
|
|
||||||
|
**Supported commands:** Any valid mpv JSON IPC command array (`["cycle", "pause"]`, `["seek", 5]`, `["script-binding", "..."]`, etc.)
|
||||||
|
|
||||||
|
For subtitle-position and subtitle-track proxy commands (`sub-pos`, `sid`, `secondary-sid`), SubMiner also shows an mpv OSD notification after the command runs.
|
||||||
|
|
||||||
|
**See `config.example.jsonc`** for more keybinding examples and configuration options.
|
||||||
|
|
||||||
|
### Shortcuts Configuration
|
||||||
|
|
||||||
|
Customize or disable the overlay keyboard shortcuts:
|
||||||
|
|
||||||
|
See `config.example.jsonc` for detailed configuration options.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"shortcuts": {
|
||||||
|
"toggleVisibleOverlayGlobal": "Alt+Shift+O",
|
||||||
|
"copySubtitle": "CommandOrControl+C",
|
||||||
|
"copySubtitleMultiple": "CommandOrControl+Shift+C",
|
||||||
|
"updateLastCardFromClipboard": "CommandOrControl+V",
|
||||||
|
"triggerFieldGrouping": "CommandOrControl+G",
|
||||||
|
"triggerSubsync": "Ctrl+Alt+S",
|
||||||
|
"mineSentence": "CommandOrControl+S",
|
||||||
|
"mineSentenceMultiple": "CommandOrControl+Shift+S",
|
||||||
|
"markAudioCard": "CommandOrControl+Shift+A",
|
||||||
|
"openRuntimeOptions": "CommandOrControl+Shift+O",
|
||||||
|
"openJimaku": "Ctrl+Shift+J",
|
||||||
|
"multiCopyTimeoutMs": 3000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Values | Description |
|
||||||
|
| ----------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `toggleVisibleOverlayGlobal` | string \| `null` | Global accelerator for toggling visible subtitle overlay (default: `"Alt+Shift+O"`) |
|
||||||
|
| `copySubtitle` | string \| `null` | Accelerator for copying current subtitle (default: `"CommandOrControl+C"`) |
|
||||||
|
| `copySubtitleMultiple` | string \| `null` | Accelerator for multi-copy mode (default: `"CommandOrControl+Shift+C"`) |
|
||||||
|
| `updateLastCardFromClipboard` | string \| `null` | Accelerator for updating card from clipboard (default: `"CommandOrControl+V"`) |
|
||||||
|
| `triggerFieldGrouping` | string \| `null` | Accelerator for Kiku field grouping on last card (default: `"CommandOrControl+G"`; only active when `behavior.autoUpdateNewCards` is `false`) |
|
||||||
|
| `triggerSubsync` | string \| `null` | Accelerator for running Subsync (default: `"Ctrl+Alt+S"`) |
|
||||||
|
| `mineSentence` | string \| `null` | Accelerator for creating sentence card from current subtitle (default: `"CommandOrControl+S"`) |
|
||||||
|
| `mineSentenceMultiple` | string \| `null` | Accelerator for multi-mine sentence card mode (default: `"CommandOrControl+Shift+S"`) |
|
||||||
|
| `multiCopyTimeoutMs` | number | Timeout in ms for multi-copy/mine digit input (default: `3000`) |
|
||||||
|
| `toggleSecondarySub` | string \| `null` | Accelerator for cycling secondary subtitle mode (default: `"CommandOrControl+Shift+V"`) |
|
||||||
|
| `markAudioCard` | string \| `null` | Accelerator for marking last card as audio card (default: `"CommandOrControl+Shift+A"`) |
|
||||||
|
| `openRuntimeOptions` | string \| `null` | Opens runtime options palette for live session-only toggles (default: `"CommandOrControl+Shift+O"`) |
|
||||||
|
| `openJimaku` | string \| `null` | Opens the Jimaku search modal (default: `"Ctrl+Shift+J"`) |
|
||||||
|
|
||||||
|
**See `config.example.jsonc`** for the complete list of shortcut configuration options.
|
||||||
|
|
||||||
|
Set any shortcut to `null` to disable it.
|
||||||
|
|
||||||
|
Feature-dependent shortcuts/keybindings only run when their related integration is enabled. For example, Anki/Kiku shortcuts require `ankiConnect.enabled` (and Kiku-specific behavior where applicable), and Jellyfin remote startup behavior requires Jellyfin to be enabled.
|
||||||
|
|
||||||
|
### Manual Card Update Shortcuts
|
||||||
|
|
||||||
|
When `behavior.autoUpdateNewCards` is set to `false`, new cards are detected but not automatically updated. Use these keyboard shortcuts for manual control:
|
||||||
|
|
||||||
|
| Shortcut | Action |
|
||||||
|
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||||
|
| `Ctrl+C` | Copy the current subtitle line to clipboard (preserves line breaks) |
|
||||||
|
| `Ctrl+Shift+C` | Enter multi-copy mode. Press `1-9` to copy that many recent lines, or `Esc` to cancel. Timeout: 3 seconds |
|
||||||
|
| `Ctrl+V` | Update the last added Anki card using subtitles from clipboard |
|
||||||
|
| `Ctrl+G` | Trigger Kiku duplicate field grouping for the last added card (only when `behavior.autoUpdateNewCards` is `false`) |
|
||||||
|
| `Ctrl+S` | Create a sentence card from the current subtitle line |
|
||||||
|
| `Ctrl+Shift+S` | Enter multi-mine mode. Press `1-9` to create a sentence card from that many recent lines, or `Esc` to cancel |
|
||||||
|
| `Ctrl+Shift+V` | Cycle secondary subtitle display mode (hidden → visible → hover) |
|
||||||
|
| `Ctrl+Shift+A` | Mark the last added Anki card as an audio card (sets IsAudioCard, SentenceAudio, Sentence, Picture) |
|
||||||
|
| `Ctrl+Shift+O` | Open runtime options palette (session-only live toggles) |
|
||||||
|
| `Ctrl/Cmd+A` | Append clipboard video path to MPV playlist (fixed, not currently configurable) |
|
||||||
|
|
||||||
|
**Multi-line copy workflow:**
|
||||||
|
|
||||||
|
1. Press `Ctrl+Shift+C`
|
||||||
|
2. Press a number key (`1-9`) within 3 seconds
|
||||||
|
3. The specified number of most recent subtitle lines are copied
|
||||||
|
4. Press `Ctrl+V` to update the last added card with the copied lines
|
||||||
|
|
||||||
|
These shortcuts are only active when the overlay window is visible and automatically disabled when hidden.
|
||||||
|
|
||||||
|
### Session Help Modal
|
||||||
|
|
||||||
|
The session help modal is opened with `Y-H` by default (falls back to `Y-K` if needed) and shows the current session keybindings and color legend.
|
||||||
|
|
||||||
|
You can filter the modal quickly with `/`:
|
||||||
|
|
||||||
|
- Type any part of the action name or shortcut in the search bar.
|
||||||
|
- Search is case-insensitive and ignores spaces/punctuation (`+`, `-`, `_`, `/`) so `ctrl w`, `ctrl+w`, and `ctrl+s` all match.
|
||||||
|
- Results are filtered across active MPV shortcuts, configured overlay shortcuts, and color legend items.
|
||||||
|
|
||||||
|
While the modal is open:
|
||||||
|
|
||||||
|
- `Esc`: close the modal (or clear the filter when text is entered)
|
||||||
|
- `↑/↓`, `j/k`: move selection
|
||||||
|
- Mouse/trackpad: click to select and activate rows
|
||||||
|
|
||||||
|
The list is generated at runtime from:
|
||||||
|
|
||||||
|
- Your active mpv keybindings (`keybindings`).
|
||||||
|
- Your configured overlay shortcuts (`shortcuts`, including runtime-loaded config values).
|
||||||
|
- Current subtitle color settings from `subtitleStyle`.
|
||||||
|
|
||||||
|
When config hot-reload updates shortcut/keybinding/style values, close and reopen the help modal to refresh the displayed entries.
|
||||||
|
|
||||||
|
### Runtime Option Palette
|
||||||
|
|
||||||
|
Use the runtime options palette to toggle settings live while SubMiner is running. These changes are session-only and reset on restart.
|
||||||
|
|
||||||
|
Current runtime options:
|
||||||
|
|
||||||
|
- `ankiConnect.behavior.autoUpdateNewCards` (`On` / `Off`)
|
||||||
|
- `ankiConnect.nPlusOne.highlightEnabled` (`On` / `Off`)
|
||||||
|
- `subtitleStyle.enableJlpt` (`On` / `Off`)
|
||||||
|
- `subtitleStyle.frequencyDictionary.enabled` (`On` / `Off`)
|
||||||
|
- `ankiConnect.nPlusOne.matchMode` (`headword` / `surface`)
|
||||||
|
- `ankiConnect.isKiku.fieldGrouping` (`auto` / `manual` / `disabled`)
|
||||||
|
|
||||||
|
Annotation toggles (`nPlusOne`, `enableJlpt`, `frequencyDictionary.enabled`) only apply to new subtitle lines after the toggle. The currently displayed line is not re-tokenized in place.
|
||||||
|
|
||||||
|
Default shortcut: `Ctrl+Shift+O`
|
||||||
|
|
||||||
|
Palette controls:
|
||||||
|
|
||||||
|
- `Arrow Up/Down`: select option
|
||||||
|
- `Arrow Left/Right`: change selected value
|
||||||
|
- `Enter`: apply selected value
|
||||||
|
- `Esc`: close
|
||||||
|
|
||||||
|
## Anki Integration
|
||||||
|
|
||||||
### AnkiConnect
|
### AnkiConnect
|
||||||
|
|
||||||
Enable automatic Anki card creation and updates with media generation:
|
Enable automatic Anki card creation and updates with media generation:
|
||||||
@@ -281,84 +720,27 @@ To refresh roughly once per day, set:
|
|||||||
|
|
||||||
<a :href="'/assets/kiku-integration.webm'" target="_blank" rel="noreferrer">Open demo in a new tab</a>
|
<a :href="'/assets/kiku-integration.webm'" target="_blank" rel="noreferrer">Open demo in a new tab</a>
|
||||||
|
|
||||||
**Image Quality Notes:**
|
## External Integrations
|
||||||
|
|
||||||
- `imageQuality` affects JPG and WebP only; PNG is lossless and ignores this setting
|
### Jimaku
|
||||||
- JPG quality is mapped to FFmpeg's scale (2-31, lower = better)
|
|
||||||
- WebP quality uses FFmpeg's native 0-100 scale
|
|
||||||
|
|
||||||
### Manual Card Update Shortcuts
|
Configure Jimaku API access and defaults:
|
||||||
|
|
||||||
When `behavior.autoUpdateNewCards` is set to `false`, new cards are detected but not automatically updated. Use these keyboard shortcuts for manual control:
|
|
||||||
|
|
||||||
| Shortcut | Action |
|
|
||||||
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
||||||
| `Ctrl+C` | Copy the current subtitle line to clipboard (preserves line breaks) |
|
|
||||||
| `Ctrl+Shift+C` | Enter multi-copy mode. Press `1-9` to copy that many recent lines, or `Esc` to cancel. Timeout: 3 seconds |
|
|
||||||
| `Ctrl+V` | Update the last added Anki card using subtitles from clipboard |
|
|
||||||
| `Ctrl+G` | Trigger Kiku duplicate field grouping for the last added card (only when `behavior.autoUpdateNewCards` is `false`) |
|
|
||||||
| `Ctrl+S` | Create a sentence card from the current subtitle line |
|
|
||||||
| `Ctrl+Shift+S` | Enter multi-mine mode. Press `1-9` to create a sentence card from that many recent lines, or `Esc` to cancel |
|
|
||||||
| `Ctrl+Shift+V` | Cycle secondary subtitle display mode (hidden → visible → hover) |
|
|
||||||
| `Ctrl+Shift+A` | Mark the last added Anki card as an audio card (sets IsAudioCard, SentenceAudio, Sentence, Picture) |
|
|
||||||
| `Ctrl+Shift+O` | Open runtime options palette (session-only live toggles) |
|
|
||||||
| `Ctrl/Cmd+A` | Append clipboard video path to MPV playlist (fixed, not currently configurable) |
|
|
||||||
|
|
||||||
**Multi-line copy workflow:**
|
|
||||||
|
|
||||||
1. Press `Ctrl+Shift+C`
|
|
||||||
2. Press a number key (`1-9`) within 3 seconds
|
|
||||||
3. The specified number of most recent subtitle lines are copied
|
|
||||||
4. Press `Ctrl+V` to update the last added card with the copied lines
|
|
||||||
|
|
||||||
These shortcuts are only active when the overlay window is visible and automatically disabled when hidden.
|
|
||||||
|
|
||||||
### Session help modal
|
|
||||||
|
|
||||||
The session help modal is opened with `Y-H` by default (falls back to `Y-K` if needed) and shows the current session keybindings and color legend.
|
|
||||||
|
|
||||||
You can filter the modal quickly with `/`:
|
|
||||||
|
|
||||||
- Type any part of the action name or shortcut in the search bar.
|
|
||||||
- Search is case-insensitive and ignores spaces/punctuation (`+`, `-`, `_`, `/`) so `ctrl w`, `ctrl+w`, and `ctrl+s` all match.
|
|
||||||
- Results are filtered across active MPV shortcuts, configured overlay shortcuts, and color legend items.
|
|
||||||
|
|
||||||
While the modal is open:
|
|
||||||
|
|
||||||
- `Esc`: close the modal (or clear the filter when text is entered)
|
|
||||||
- `↑/↓`, `j/k`: move selection
|
|
||||||
- Mouse/trackpad: click to select and activate rows
|
|
||||||
|
|
||||||
The list is generated at runtime from:
|
|
||||||
|
|
||||||
- Your active mpv keybindings (`keybindings`).
|
|
||||||
- Your configured overlay shortcuts (`shortcuts`, including runtime-loaded config values).
|
|
||||||
- Current subtitle color settings from `subtitleStyle`.
|
|
||||||
|
|
||||||
When config hot-reload updates shortcut/keybinding/style values, close and reopen the help modal to refresh the displayed entries.
|
|
||||||
|
|
||||||
### Auto-Start Overlay
|
|
||||||
|
|
||||||
Control whether the overlay automatically becomes visible when it connects to mpv:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"auto_start_overlay": false
|
"jimaku": {
|
||||||
|
"apiKey": "YOUR_API_KEY",
|
||||||
|
"apiKeyCommand": "cat ~/.jimaku_key",
|
||||||
|
"apiBaseUrl": "https://jimaku.cc",
|
||||||
|
"languagePreference": "ja",
|
||||||
|
"maxEntryResults": 10
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
| Option | Values | Description |
|
Jimaku is rate limited; if you hit a limit, SubMiner will surface the retry delay from the API response.
|
||||||
| -------------------- | --------------- | ------------------------------------------------------ |
|
|
||||||
| `auto_start_overlay` | `true`, `false` | Auto-show overlay on mpv connection (default: `false`) |
|
|
||||||
|
|
||||||
The mpv plugin controls startup overlay visibility via `auto_start_visible_overlay` in `subminer.conf`.
|
Set `openBrowser` to `false` to only print the URL without opening a browser.
|
||||||
For wrapper-driven playback, `subminer.conf` can also enable startup pause gating with
|
|
||||||
`auto_start_pause_until_ready` (requires `auto_start=yes` + `auto_start_visible_overlay=yes`).
|
|
||||||
Current plugin defaults in `subminer.conf` are:
|
|
||||||
|
|
||||||
- `auto_start=yes`
|
|
||||||
- `auto_start_visible_overlay=yes`
|
|
||||||
- `auto_start_pause_until_ready=yes`
|
|
||||||
|
|
||||||
### Auto Subtitle Sync
|
### Auto Subtitle Sync
|
||||||
|
|
||||||
@@ -385,35 +767,6 @@ Sync the active subtitle track using `alass` (preferred) or `ffsubsync`:
|
|||||||
Default trigger is `Ctrl+Alt+S` via `shortcuts.triggerSubsync`.
|
Default trigger is `Ctrl+Alt+S` via `shortcuts.triggerSubsync`.
|
||||||
Customize it there, or set it to `null` to disable.
|
Customize it there, or set it to `null` to disable.
|
||||||
|
|
||||||
### Subtitle Position Edit
|
|
||||||
|
|
||||||
Subtitle positioning can be adjusted directly in the overlay:
|
|
||||||
|
|
||||||
- `Ctrl/Cmd+Shift+P` toggles position edit mode.
|
|
||||||
- Use arrow keys to move subtitle text.
|
|
||||||
- Press `Enter` or `Ctrl/Cmd+S` to save, or `Esc` to cancel.
|
|
||||||
- This edit-mode shortcut is fixed (not currently configurable in `shortcuts`/`keybindings`).
|
|
||||||
|
|
||||||
### Jimaku
|
|
||||||
|
|
||||||
Configure Jimaku API access and defaults:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"jimaku": {
|
|
||||||
"apiKey": "YOUR_API_KEY",
|
|
||||||
"apiKeyCommand": "cat ~/.jimaku_key",
|
|
||||||
"apiBaseUrl": "https://jimaku.cc",
|
|
||||||
"languagePreference": "ja",
|
|
||||||
"maxEntryResults": 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Jimaku is rate limited; if you hit a limit, SubMiner will surface the retry delay from the API response.
|
|
||||||
|
|
||||||
Set `openBrowser` to `false` to only print the URL without opening a browser.
|
|
||||||
|
|
||||||
### AniList
|
### AniList
|
||||||
|
|
||||||
AniList integration is opt-in and disabled by default. Enable it to allow SubMiner to update watched episode progress after playback.
|
AniList integration is opt-in and disabled by default. Enable it to allow SubMiner to update watched episode progress after playback.
|
||||||
@@ -561,322 +914,6 @@ Troubleshooting:
|
|||||||
- If images do not render, confirm asset keys exactly match uploaded Discord asset names.
|
- If images do not render, confirm asset keys exactly match uploaded Discord asset names.
|
||||||
- If Discord is closed/not installed/disconnects, SubMiner continues running and quietly skips presence updates.
|
- If Discord is closed/not installed/disconnects, SubMiner continues running and quietly skips presence updates.
|
||||||
|
|
||||||
### Keybindings
|
|
||||||
|
|
||||||
Add a `keybindings` array to configure keyboard shortcuts that send commands to mpv:
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options and more examples.
|
|
||||||
|
|
||||||
**Default keybindings:**
|
|
||||||
|
|
||||||
| Key | Command | Description |
|
|
||||||
| ----------------- | ---------------------------- | ------------------------------------- |
|
|
||||||
| `Space` | `["cycle", "pause"]` | Toggle pause |
|
|
||||||
| `KeyJ` | `["cycle", "sid"]` | Cycle primary subtitle track |
|
|
||||||
| `Shift+KeyJ` | `["cycle", "secondary-sid"]` | Cycle secondary subtitle track |
|
|
||||||
| `ArrowRight` | `["seek", 5]` | Seek forward 5 seconds |
|
|
||||||
| `ArrowLeft` | `["seek", -5]` | Seek backward 5 seconds |
|
|
||||||
| `ArrowUp` | `["seek", 60]` | Seek forward 60 seconds |
|
|
||||||
| `ArrowDown` | `["seek", -60]` | Seek backward 60 seconds |
|
|
||||||
| `Shift+KeyH` | `["sub-seek", -1]` | Jump to previous subtitle |
|
|
||||||
| `Shift+KeyL` | `["sub-seek", 1]` | Jump to next subtitle |
|
|
||||||
| `Ctrl+Shift+KeyH` | `["__replay-subtitle"]` | Replay current subtitle, pause at end |
|
|
||||||
| `Ctrl+Shift+KeyL` | `["__play-next-subtitle"]` | Play next subtitle, pause at end |
|
|
||||||
| `KeyQ` | `["quit"]` | Quit mpv |
|
|
||||||
| `Ctrl+KeyW` | `["quit"]` | Quit mpv |
|
|
||||||
|
|
||||||
**Custom keybindings example:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"keybindings": [
|
|
||||||
{ "key": "ArrowRight", "command": ["seek", 5] },
|
|
||||||
{ "key": "ArrowLeft", "command": ["seek", -5] },
|
|
||||||
{ "key": "Shift+ArrowRight", "command": ["seek", 30] },
|
|
||||||
{ "key": "KeyR", "command": ["script-binding", "immersive/auto-replay"] },
|
|
||||||
{ "key": "KeyA", "command": ["script-message", "ankiconnect-add-note"] }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Key format:** Use `KeyboardEvent.code` values (`Space`, `ArrowRight`, `KeyR`, etc.) with optional modifiers (`Ctrl+`, `Alt+`, `Shift+`, `Meta+`).
|
|
||||||
|
|
||||||
**Disable a default binding:** Set command to `null`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{ "key": "Space", "command": null }
|
|
||||||
```
|
|
||||||
|
|
||||||
**Special commands:** Commands prefixed with `__` are handled internally by the overlay rather than sent to mpv. `__replay-subtitle` replays the current subtitle and pauses at its end. `__play-next-subtitle` seeks to the next subtitle, plays it, and pauses at its end. `__runtime-options-open` opens the runtime options palette. `__runtime-option-cycle:<id>[:next|prev]` cycles a runtime option value.
|
|
||||||
|
|
||||||
**Supported commands:** Any valid mpv JSON IPC command array (`["cycle", "pause"]`, `["seek", 5]`, `["script-binding", "..."]`, etc.)
|
|
||||||
|
|
||||||
For subtitle-position and subtitle-track proxy commands (`sub-pos`, `sid`, `secondary-sid`), SubMiner also shows an mpv OSD notification after the command runs.
|
|
||||||
|
|
||||||
**See `config.example.jsonc`** for more keybinding examples and configuration options.
|
|
||||||
|
|
||||||
### Runtime Option Palette
|
|
||||||
|
|
||||||
Use the runtime options palette to toggle settings live while SubMiner is running. These changes are session-only and reset on restart.
|
|
||||||
|
|
||||||
Current runtime options:
|
|
||||||
|
|
||||||
- `ankiConnect.behavior.autoUpdateNewCards` (`On` / `Off`)
|
|
||||||
- `ankiConnect.nPlusOne.highlightEnabled` (`On` / `Off`)
|
|
||||||
- `subtitleStyle.enableJlpt` (`On` / `Off`)
|
|
||||||
- `subtitleStyle.frequencyDictionary.enabled` (`On` / `Off`)
|
|
||||||
- `ankiConnect.nPlusOne.matchMode` (`headword` / `surface`)
|
|
||||||
- `ankiConnect.isKiku.fieldGrouping` (`auto` / `manual` / `disabled`)
|
|
||||||
|
|
||||||
Annotation toggles (`nPlusOne`, `enableJlpt`, `frequencyDictionary.enabled`) only apply to new subtitle lines after the toggle. The currently displayed line is not re-tokenized in place.
|
|
||||||
|
|
||||||
Default shortcut: `Ctrl+Shift+O`
|
|
||||||
|
|
||||||
Palette controls:
|
|
||||||
|
|
||||||
- `Arrow Up/Down`: select option
|
|
||||||
- `Arrow Left/Right`: change selected value
|
|
||||||
- `Enter`: apply selected value
|
|
||||||
- `Esc`: close
|
|
||||||
|
|
||||||
### Secondary Subtitles
|
|
||||||
|
|
||||||
Display a second subtitle track (e.g., English alongside Japanese) in the overlay:
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"secondarySub": {
|
|
||||||
"secondarySubLanguages": ["eng", "en"],
|
|
||||||
"autoLoadSecondarySub": true,
|
|
||||||
"defaultMode": "hover"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| ----------------------- | ---------------------------------- | ------------------------------------------------------ |
|
|
||||||
| `secondarySubLanguages` | string[] | Language codes to auto-load (e.g., `["eng", "en"]`) |
|
|
||||||
| `autoLoadSecondarySub` | `true`, `false` | Auto-detect and load matching secondary subtitle track |
|
|
||||||
| `defaultMode` | `"hidden"`, `"visible"`, `"hover"` | Initial display mode (default: `"hover"`) |
|
|
||||||
|
|
||||||
**Display modes:**
|
|
||||||
|
|
||||||
- **hidden** — Secondary subtitles not shown
|
|
||||||
- **visible** — Always visible at top of overlay
|
|
||||||
- **hover** — Only visible when hovering over the subtitle area (default)
|
|
||||||
|
|
||||||
**See `config.example.jsonc`** for additional secondary subtitle configuration options.
|
|
||||||
|
|
||||||
### Shortcuts Configuration
|
|
||||||
|
|
||||||
Customize or disable the overlay keyboard shortcuts:
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"shortcuts": {
|
|
||||||
"toggleVisibleOverlayGlobal": "Alt+Shift+O",
|
|
||||||
"copySubtitle": "CommandOrControl+C",
|
|
||||||
"copySubtitleMultiple": "CommandOrControl+Shift+C",
|
|
||||||
"updateLastCardFromClipboard": "CommandOrControl+V",
|
|
||||||
"triggerFieldGrouping": "CommandOrControl+G",
|
|
||||||
"triggerSubsync": "Ctrl+Alt+S",
|
|
||||||
"mineSentence": "CommandOrControl+S",
|
|
||||||
"mineSentenceMultiple": "CommandOrControl+Shift+S",
|
|
||||||
"markAudioCard": "CommandOrControl+Shift+A",
|
|
||||||
"openRuntimeOptions": "CommandOrControl+Shift+O",
|
|
||||||
"openJimaku": "Ctrl+Shift+J",
|
|
||||||
"multiCopyTimeoutMs": 3000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| ----------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `toggleVisibleOverlayGlobal` | string \| `null` | Global accelerator for toggling visible subtitle overlay (default: `"Alt+Shift+O"`) |
|
|
||||||
| `copySubtitle` | string \| `null` | Accelerator for copying current subtitle (default: `"CommandOrControl+C"`) |
|
|
||||||
| `copySubtitleMultiple` | string \| `null` | Accelerator for multi-copy mode (default: `"CommandOrControl+Shift+C"`) |
|
|
||||||
| `updateLastCardFromClipboard` | string \| `null` | Accelerator for updating card from clipboard (default: `"CommandOrControl+V"`) |
|
|
||||||
| `triggerFieldGrouping` | string \| `null` | Accelerator for Kiku field grouping on last card (default: `"CommandOrControl+G"`; only active when `behavior.autoUpdateNewCards` is `false`) |
|
|
||||||
| `triggerSubsync` | string \| `null` | Accelerator for running Subsync (default: `"Ctrl+Alt+S"`) |
|
|
||||||
| `mineSentence` | string \| `null` | Accelerator for creating sentence card from current subtitle (default: `"CommandOrControl+S"`) |
|
|
||||||
| `mineSentenceMultiple` | string \| `null` | Accelerator for multi-mine sentence card mode (default: `"CommandOrControl+Shift+S"`) |
|
|
||||||
| `multiCopyTimeoutMs` | number | Timeout in ms for multi-copy/mine digit input (default: `3000`) |
|
|
||||||
| `toggleSecondarySub` | string \| `null` | Accelerator for cycling secondary subtitle mode (default: `"CommandOrControl+Shift+V"`) |
|
|
||||||
| `markAudioCard` | string \| `null` | Accelerator for marking last card as audio card (default: `"CommandOrControl+Shift+A"`) |
|
|
||||||
| `openRuntimeOptions` | string \| `null` | Opens runtime options palette for live session-only toggles (default: `"CommandOrControl+Shift+O"`) |
|
|
||||||
| `openJimaku` | string \| `null` | Opens the Jimaku search modal (default: `"Ctrl+Shift+J"`) |
|
|
||||||
|
|
||||||
**See `config.example.jsonc`** for the complete list of shortcut configuration options.
|
|
||||||
|
|
||||||
Set any shortcut to `null` to disable it.
|
|
||||||
|
|
||||||
Feature-dependent shortcuts/keybindings only run when their related integration is enabled. For example, Anki/Kiku shortcuts require `ankiConnect.enabled` (and Kiku-specific behavior where applicable), and Jellyfin remote startup behavior requires Jellyfin to be enabled.
|
|
||||||
|
|
||||||
### Subtitle Position
|
|
||||||
|
|
||||||
Set the initial vertical subtitle position (measured from the bottom of the screen):
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"subtitlePosition": {
|
|
||||||
"yPercent": 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| ---------- | ---------------- | ---------------------------------------------------------------------- |
|
|
||||||
| `yPercent` | number (0 - 100) | Distance from the bottom as a percent of screen height (default: `10`) |
|
|
||||||
|
|
||||||
### Subtitle Style
|
|
||||||
|
|
||||||
Customize the appearance of primary and secondary subtitles:
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"subtitleStyle": {
|
|
||||||
"fontFamily": "M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP",
|
|
||||||
"fontSize": 35,
|
|
||||||
"fontColor": "#cad3f5",
|
|
||||||
"fontWeight": "600",
|
|
||||||
"lineHeight": 1.35,
|
|
||||||
"letterSpacing": "-0.01em",
|
|
||||||
"wordSpacing": 0,
|
|
||||||
"fontKerning": "normal",
|
|
||||||
"textRendering": "geometricPrecision",
|
|
||||||
"textShadow": "0 3px 10px rgba(0,0,0,0.69)",
|
|
||||||
"fontStyle": "normal",
|
|
||||||
"backgroundColor": "rgb(30, 32, 48, 0.88)",
|
|
||||||
"backdropFilter": "blur(6px)",
|
|
||||||
"secondary": {
|
|
||||||
"fontFamily": "Manrope, Inter",
|
|
||||||
"fontSize": 24,
|
|
||||||
"fontColor": "#cad3f5",
|
|
||||||
"backgroundColor": "transparent"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| ---------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `fontFamily` | string | CSS font-family value (default: `"M PLUS 1 Medium, Source Han Sans JP, Noto Sans CJK JP"`) |
|
|
||||||
| `fontSize` | number (px) | Font size in pixels (default: `35`) |
|
|
||||||
| `fontColor` | string | Any CSS color value (default: `"#cad3f5"`) |
|
|
||||||
| `fontWeight` | string | CSS font-weight, e.g. `"bold"`, `"normal"`, `"600"` (default: `"600"`) |
|
|
||||||
| `fontStyle` | string | `"normal"` or `"italic"` (default: `"normal"`) |
|
|
||||||
| `backgroundColor` | string | Any CSS color, including `"transparent"` (default: `"rgb(30, 32, 48, 0.88)"`) |
|
|
||||||
| `enableJlpt` | boolean | Enable JLPT level underline styling (`false` by default) |
|
|
||||||
| `preserveLineBreaks` | boolean | Preserve line breaks in visible overlay subtitle rendering (`false` by default). Enable to mirror mpv line layout. |
|
|
||||||
| `autoPauseVideoOnHover` | boolean | Pause playback while mouse hovers subtitle text, then resume on leave (`true` by default). |
|
|
||||||
| `frequencyDictionary.enabled` | boolean | Enable frequency highlighting from dictionary lookups (`false` by default) |
|
|
||||||
| `frequencyDictionary.sourcePath` | string | Path to a local frequency dictionary root. Leave empty or omit to use installed/default frequency-dictionary search paths. |
|
|
||||||
| `frequencyDictionary.topX` | number | Only color tokens whose frequency rank is `<= topX` (`1000` by default) |
|
|
||||||
| `frequencyDictionary.mode` | string | `"single"` or `"banded"` (`"single"` by default) |
|
|
||||||
| `frequencyDictionary.matchMode` | string | `"headword"` or `"surface"` (`"headword"` by default) |
|
|
||||||
| `frequencyDictionary.singleColor` | string | Color used for all highlighted tokens in single mode |
|
|
||||||
| `frequencyDictionary.bandedColors` | string[] | Array of five hex colors used for ranked bands in banded mode |
|
|
||||||
| `nPlusOneColor` | string | Existing n+1 highlight color (default: `#c6a0f6`) |
|
|
||||||
| `knownWordColor` | string | Existing known-word highlight color (default: `#a6da95`) |
|
|
||||||
| `jlptColors` | object | JLPT level underline colors object (`N1`..`N5`) |
|
|
||||||
| `secondary` | object | Override any of the above for secondary subtitles (optional) |
|
|
||||||
|
|
||||||
JLPT underlining is powered by offline term-meta bank files at runtime. See [`docs/jlpt-vocab-bundle.md`](jlpt-vocab-bundle.md) for required files, source/version refresh steps, and deterministic fallback behavior.
|
|
||||||
|
|
||||||
Frequency dictionary highlighting uses the same dictionary file format as JLPT bundle lookups (`term_meta_bank_*.json` under discovered dictionary directories). A token is highlighted when it has a positive integer `frequencyRank` (lower is more common) and the rank is within `topX`.
|
|
||||||
|
|
||||||
Lookup behavior:
|
|
||||||
|
|
||||||
- Set `frequencyDictionary.sourcePath` to a directory containing `term_meta_bank_*.json` for a fully custom source.
|
|
||||||
- If `sourcePath` is missing or empty, SubMiner searches default install/runtime locations for `frequency-dictionary` directories (for example app resources, user data paths, and current working directory).
|
|
||||||
- In both cases, only terms with a valid `frequencyRank` are used; everything else falls back to no highlighting.
|
|
||||||
- `frequencyDictionary.matchMode` controls which token text is used for frequency lookups: `headword` (dictionary form) or `surface` (visible subtitle text).
|
|
||||||
- Frequency highlighting skips tokens that look like non-lexical SFX/interjection noise (for example kana reduplication or short kana endings like `っ`), even when dictionary ranks exist.
|
|
||||||
|
|
||||||
In `single` mode all highlights use `singleColor`; in `banded` mode tokens map to five ascending color bands from most common to least common inside the topX window.
|
|
||||||
|
|
||||||
Secondary subtitle defaults: `fontFamily: "Manrope, Inter"`, `fontSize: 24`, `fontColor: "#cad3f5"`, `backgroundColor: "transparent"`. Any property not set in `secondary` falls back to the CSS defaults.
|
|
||||||
|
|
||||||
**See `config.example.jsonc`** for the complete list of subtitle style configuration options.
|
|
||||||
|
|
||||||
`jlptColors` keys are:
|
|
||||||
|
|
||||||
| Key | Default | Description |
|
|
||||||
| ---- | --------- | ----------------------- |
|
|
||||||
| `N1` | `#ed8796` | JLPT N1 underline color |
|
|
||||||
| `N2` | `#f5a97f` | JLPT N2 underline color |
|
|
||||||
| `N3` | `#f9e2af` | JLPT N3 underline color |
|
|
||||||
| `N4` | `#a6e3a1` | JLPT N4 underline color |
|
|
||||||
| `N5` | `#8aadf4` | JLPT N5 underline color |
|
|
||||||
|
|
||||||
### Texthooker
|
|
||||||
|
|
||||||
Control whether the browser opens automatically when texthooker starts:
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"texthooker": {
|
|
||||||
"openBrowser": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### WebSocket Server
|
|
||||||
|
|
||||||
The overlay includes a built-in WebSocket server that broadcasts subtitle text to connected clients (such as texthooker-ui) for external processing.
|
|
||||||
|
|
||||||
By default, the server uses "auto" mode: it starts automatically unless [mpv_websocket](https://github.com/kuroahna/mpv_websocket) is detected at `~/.config/mpv/mpv_websocket`. If you have mpv_websocket installed, the built-in server is skipped to avoid conflicts.
|
|
||||||
|
|
||||||
See `config.example.jsonc` for detailed configuration options.
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"websocket": {
|
|
||||||
"enabled": "auto",
|
|
||||||
"port": 6677
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| --------- | ------------------------- | -------------------------------------------------------- |
|
|
||||||
| `enabled` | `true`, `false`, `"auto"` | `"auto"` (default) disables if mpv_websocket is detected |
|
|
||||||
| `port` | number | WebSocket server port (default: 6677) |
|
|
||||||
|
|
||||||
### Startup Warmups
|
|
||||||
|
|
||||||
Control which startup warmups run in the background versus deferring to first real usage:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"startupWarmups": {
|
|
||||||
"lowPowerMode": false,
|
|
||||||
"mecab": true,
|
|
||||||
"yomitanExtension": true,
|
|
||||||
"subtitleDictionaries": true,
|
|
||||||
"jellyfinRemoteSession": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
| Option | Values | Description |
|
|
||||||
| ----------------------- | --------------- | ------------------------------------------------------------------------------------------------- |
|
|
||||||
| `lowPowerMode` | `true`, `false` | Defer all warmups except Yomitan extension |
|
|
||||||
| `mecab` | `true`, `false` | Warm up MeCab tokenizer at startup |
|
|
||||||
| `yomitanExtension` | `true`, `false` | Warm up Yomitan extension at startup |
|
|
||||||
| `subtitleDictionaries` | `true`, `false` | Warm up JLPT + frequency dictionaries at startup |
|
|
||||||
| `jellyfinRemoteSession` | `true`, `false` | Warm up Jellyfin remote session at startup (still requires Jellyfin remote auto-connect settings) |
|
|
||||||
|
|
||||||
Defaults warm everything (`true` for all toggles, `lowPowerMode: false`). Setting a warmup toggle to `false` defers that work until first usage.
|
|
||||||
|
|
||||||
### Immersion Tracking
|
### Immersion Tracking
|
||||||
|
|
||||||
Enable or disable local immersion analytics stored in SQLite for mined subtitles and media sessions:
|
Enable or disable local immersion analytics stored in SQLite for mined subtitles and media sessions:
|
||||||
|
|||||||
@@ -67,18 +67,6 @@ Mouse-hover playback behavior is configured separately from shortcuts: `subtitle
|
|||||||
| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` |
|
| `Ctrl+Shift+J` | Open Jimaku subtitle search modal | `shortcuts.openJimaku` |
|
||||||
| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` |
|
| `Ctrl+Alt+S` | Open subtitle sync (subsync) modal | `shortcuts.triggerSubsync` |
|
||||||
|
|
||||||
## Subtitle Position Edit Mode
|
|
||||||
|
|
||||||
Enter edit mode to fine-tune subtitle alignment.
|
|
||||||
|
|
||||||
| Shortcut | Action |
|
|
||||||
| --------------------- | -------------------------------- |
|
|
||||||
| `Ctrl/Cmd+Shift+P` | Toggle position edit mode |
|
|
||||||
| `ArrowKeys` or `hjkl` | Nudge position by 1 px |
|
|
||||||
| `Shift+Arrow` | Nudge position by 4 px |
|
|
||||||
| `Enter` or `Ctrl+S` | Save position and exit edit mode |
|
|
||||||
| `Esc` | Cancel and discard changes |
|
|
||||||
|
|
||||||
## MPV Plugin Chords
|
## MPV Plugin Chords
|
||||||
|
|
||||||
When the mpv plugin is installed, all commands use a `y` chord prefix — press `y`, then the second key within 1 second.
|
When the mpv plugin is installed, all commands use a `y` chord prefix — press `y`, then the second key within 1 second.
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ SubMiner positions the overlay by tracking the mpv window. If tracking fails:
|
|||||||
- Sway: Ensure `swaymsg` is available.
|
- Sway: Ensure `swaymsg` is available.
|
||||||
- X11: Ensure `xdotool` and `xwininfo` are installed.
|
- X11: Ensure `xdotool` and `xwininfo` are installed.
|
||||||
|
|
||||||
If the overlay position is slightly off, use subtitle position edit mode (`Ctrl/Cmd+Shift+P`) to fine-tune the offset with arrow keys, then save with `Enter` or `Ctrl+S`.
|
If the overlay position is slightly off, right-click and drag on subtitle text to fine-tune the overlay subtitle offset.
|
||||||
|
|
||||||
## Yomitan
|
## Yomitan
|
||||||
|
|
||||||
@@ -279,5 +279,5 @@ The Jimaku API has rate limits. If you see 429 errors, wait for the retry durati
|
|||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
- **Accessibility permission**: Required for window tracking. Grant it in System Settings > Privacy & Security > Accessibility.
|
- **Accessibility permission**: Required for window tracking. Grant it in System Settings > Privacy & Security > Accessibility.
|
||||||
- **Font rendering**: macOS uses a 0.87x font compensation factor for subtitle alignment between mpv and the overlay. If text alignment looks off, adjust subtitle offset in position edit mode.
|
- **Font rendering**: macOS uses a 0.87x font compensation factor for subtitle alignment between mpv and the overlay. If text alignment looks off, adjust subtitle offset by right-click dragging subtitle text.
|
||||||
- **Gatekeeper**: If macOS blocks SubMiner, right-click the app and select "Open" to bypass the warning, or remove the quarantine attribute: `xattr -d com.apple.quarantine /path/to/SubMiner.app`
|
- **Gatekeeper**: If macOS blocks SubMiner, right-click the app and select "Open" to bypass the warning, or remove the quarantine attribute: `xattr -d com.apple.quarantine /path/to/SubMiner.app`
|
||||||
|
|||||||
@@ -192,10 +192,6 @@ Notes:
|
|||||||
| `Ctrl+W` | Quit mpv |
|
| `Ctrl+W` | Quit mpv |
|
||||||
| `Right-click` | Toggle MPV pause (outside subtitle area) |
|
| `Right-click` | Toggle MPV pause (outside subtitle area) |
|
||||||
| `Right-click + drag` | Move subtitle position (on subtitle) |
|
| `Right-click + drag` | Move subtitle position (on subtitle) |
|
||||||
| `Ctrl/Cmd+Shift+P` | Toggle subtitle position edit mode |
|
|
||||||
| `Arrow keys` | Move subtitles while edit mode is active |
|
|
||||||
| `Enter` / `Ctrl+S` | Save subtitle position in edit mode |
|
|
||||||
| `Esc` | Cancel subtitle position edit mode |
|
|
||||||
| `Ctrl/Cmd+A` | Append clipboard video path to MPV playlist |
|
| `Ctrl/Cmd+A` | Append clipboard video path to MPV playlist |
|
||||||
|
|
||||||
These keybindings only work when the overlay window has focus. See [Configuration](/configuration) for customization.
|
These keybindings only work when the overlay window has focus. See [Configuration](/configuration) for customization.
|
||||||
|
|||||||
Reference in New Issue
Block a user