mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-10 04:46:07 -08:00
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Claude <noreply@anthropic.com>
1158 lines
83 KiB
JSON
1158 lines
83 KiB
JSON
/**
|
||
* SubMiner Example Configuration File
|
||
*
|
||
* This file is auto-generated from src/config/definitions.ts.
|
||
* Copy to %APPDATA%/SubMiner/config.jsonc on Windows, or $XDG_CONFIG_HOME/SubMiner/config.jsonc (or ~/.config/SubMiner/config.jsonc) on Linux/macOS.
|
||
*/
|
||
{
|
||
|
||
// ==========================================
|
||
// Dictionary Backend
|
||
// Select the dictionary lookup backend: yomitan or hachidori.
|
||
// Restart SubMiner after changing the backend. Each backend keeps separate settings and dictionaries.
|
||
// ==========================================
|
||
"dictionaryBackend": "yomitan", // Dictionary lookup backend. Restart SubMiner after changing this setting. Values: yomitan | hachidori
|
||
|
||
// ==========================================
|
||
// Subtitle Selection
|
||
// Select primary and secondary mpv subtitle tracks from the overlay.
|
||
// Hot-reload: enabling or disabling updates the session shortcut immediately.
|
||
// ==========================================
|
||
"subtitleSelection": {
|
||
"enabled": false // Use the SubMiner modal to select primary and secondary subtitle tracks. When enabled, its shortcut overrides mpv subtitle selection. Values: true | false
|
||
}, // Select primary and secondary mpv subtitle tracks from the overlay.
|
||
|
||
// ==========================================
|
||
// Japanese Subtitle Generation
|
||
// Generate timed Japanese subtitles from local audio using whisper.cpp.
|
||
// Configure an existing GGML model path or explicitly download a SubMiner-managed model.
|
||
// Hot-reload: settings apply to the next generation or model download.
|
||
// ==========================================
|
||
"subtitleGeneration": {
|
||
"whisperPath": "", // Optional path override for whisper.cpp. Leave empty to find whisper-cli on PATH.
|
||
"modelPath": "", // Path to an existing multilingual whisper.cpp GGML model. Leave empty to use a SubMiner-managed model. A configured path always takes precedence.
|
||
"managedModel": "small", // Multilingual whisper.cpp model to use when modelPath is empty. Download it explicitly from the generation modal or launcher. Values: tiny | tiny-q5_1 | tiny-q8_0 | base | base-q5_1 | base-q8_0 | small | small-q5_1 | small-q8_0 | medium | medium-q5_0 | medium-q8_0 | large-v1 | large-v2 | large-v2-q5_0 | large-v2-q8_0 | large-v3 | large-v3-q5_0 | large-v3-turbo | large-v3-turbo-q5_0 | large-v3-turbo-q8_0
|
||
"threads": 4, // Positive integer CPU thread count for whisper.cpp Japanese transcription.
|
||
"ffmpegPath": "", // Optional FFmpeg path override for audio extraction. Leave empty to find ffmpeg on PATH.
|
||
"ffprobePath": "", // Optional FFprobe path override for audio tracks and timing. Leave empty to find ffprobe on PATH.
|
||
"vadModelPath": "", // Path to a whisper.cpp Silero VAD model. Enables dialogue-focused generation while retaining uncertain audible sections, which may include songs. Leave empty to transcribe the full audio.
|
||
"vadPath": "" // Optional speech detector executable override. With vadModelPath configured, leave empty to find whisper-vad-speech-segments or vad-speech-segments on PATH.
|
||
}, // Generate timed Japanese subtitles from local audio using whisper.cpp.
|
||
|
||
// ==========================================
|
||
// Visible Overlay Auto-Start
|
||
// Show the visible subtitle overlay automatically after managed mpv playback starts SubMiner.
|
||
// SubMiner can still auto-start in the background when this is false.
|
||
// ==========================================
|
||
"auto_start_overlay": true, // Show the visible subtitle overlay automatically when the bundled mpv plugin starts SubMiner. Values: true | false
|
||
|
||
// ==========================================
|
||
// Texthooker Server
|
||
// Configure texthooker startup launch and browser opening behavior.
|
||
// ==========================================
|
||
"texthooker": {
|
||
"launchAtStartup": false, // Launch texthooker server automatically when SubMiner starts. Values: true | false
|
||
"openBrowser": false // Open the texthooker page in the default browser when the server starts. Values: true | false
|
||
}, // Configure texthooker startup launch and browser opening behavior.
|
||
|
||
// ==========================================
|
||
// WebSocket Server
|
||
// Built-in WebSocket server broadcasts subtitle text to connected clients.
|
||
// Auto mode disables built-in server if mpv_websocket is detected.
|
||
// ==========================================
|
||
"websocket": {
|
||
"enabled": false, // Built-in subtitle websocket server mode. Values: auto | true | false
|
||
"port": 6677 // Built-in subtitle websocket server port.
|
||
}, // Built-in WebSocket server broadcasts subtitle text to connected clients.
|
||
|
||
// ==========================================
|
||
// Annotation WebSocket
|
||
// Dedicated annotated subtitle websocket for bundled texthooker and token-aware clients.
|
||
// Independent from websocket.auto and defaults to port 6678.
|
||
// ==========================================
|
||
"annotationWebsocket": {
|
||
"enabled": false, // Annotated subtitle websocket server enabled state. Values: true | false
|
||
"port": 6678 // Annotated subtitle websocket server port.
|
||
}, // Dedicated annotated subtitle websocket for bundled texthooker and token-aware clients.
|
||
|
||
// ==========================================
|
||
// Logging
|
||
// Controls logging verbosity.
|
||
// Set to debug for full runtime diagnostics.
|
||
// Hot-reload: logging.level and logging.files apply live while SubMiner is running.
|
||
// ==========================================
|
||
"logging": {
|
||
"level": "warn", // Minimum log level for runtime logging. Values: debug | info | warn | error
|
||
"rotation": 7, // Number of days of app, launcher, and mpv logs to retain.
|
||
"files": {
|
||
"app": true, // Write SubMiner app runtime logs. Values: true | false
|
||
"launcher": true, // Write launcher command logs. Values: true | false
|
||
"mpv": false // Write mpv player logs. Enable temporarily when debugging mpv/plugin startup. Values: true | false
|
||
} // Files setting.
|
||
}, // Controls logging verbosity.
|
||
|
||
// ==========================================
|
||
// Controller Support
|
||
// Gamepad support for the visible overlay while keyboard-only mode is active.
|
||
// Use Alt+C to pick a preferred controller and remap actions inline with learn mode.
|
||
// Trigger input mode can be auto, digital-only, or analog-thresholded depending on the controller.
|
||
// Override controller.buttonIndices when your pad reports non-standard raw button numbers.
|
||
// ==========================================
|
||
"controller": {
|
||
"enabled": false, // Enable overlay controller support through the Chrome Gamepad API. Values: true | false
|
||
"preferredGamepadId": "", // Preferred controller id saved from the controller config modal.
|
||
"preferredGamepadLabel": "", // Preferred controller display label saved for diagnostics.
|
||
"smoothScroll": true, // Use smooth scrolling for controller-driven popup scroll input. Values: true | false
|
||
"scrollPixelsPerSecond": 900, // Base popup scroll speed for controller stick input.
|
||
"horizontalJumpPixels": 160, // Popup page-jump distance for controller jump input.
|
||
"stickDeadzone": 0.2, // Deadzone applied to controller stick axes.
|
||
"triggerInputMode": "auto", // How controller triggers are interpreted: auto, pressed-only, or thresholded analog. Values: auto | digital | analog
|
||
"triggerDeadzone": 0.5, // Minimum analog trigger value required when trigger input uses auto or analog mode.
|
||
"faceButtonLabels": "xbox", // Face button style of your controller: xbox (A at the bottom), nintendo (A on the right, B at the bottom; Switch-style and many 8BitDo pads) or playstation (╳ ○ □ △, laid out like xbox). Places the A/B/X/Y of the dialog layouts and names buttons in Alt+C and the dialog hints. Alt+C sets it per controller (controller.profiles.<id>.faceButtonLabels); this is the default for the others. Values: xbox | nintendo | playstation
|
||
"repeatDelayMs": 320, // Delay before repeating held controller actions.
|
||
"repeatIntervalMs": 120, // Repeat interval for held controller actions.
|
||
"buttonIndices": {
|
||
"select": 6, // Raw button index used for the controller select/minus/back button.
|
||
"buttonSouth": 0, // Raw button index used for controller south/A button input.
|
||
"buttonEast": 1, // Raw button index used for controller east/B button input.
|
||
"buttonWest": 2, // Raw button index used for controller west/X button input.
|
||
"buttonNorth": 3, // Raw button index used for controller north/Y button input.
|
||
"leftShoulder": 4, // Raw button index used for controller left shoulder input.
|
||
"rightShoulder": 5, // Raw button index used for controller right shoulder input.
|
||
"leftStickPress": 9, // Raw button index used for controller L3 input.
|
||
"rightStickPress": 10, // Raw button index used for controller R3 input.
|
||
"leftTrigger": 6, // Raw button index used for controller L2 input.
|
||
"rightTrigger": 7 // Raw button index used for controller R2 input.
|
||
}, // Semantic button-name reference mapping used for debug output. Updating it does not rewrite existing raw binding descriptors.
|
||
"bindings": {
|
||
"toggleLookup": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 0 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for toggling lookup. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"closeLookup": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 1 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for closing lookup. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"toggleKeyboardOnlyMode": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 3 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for toggling keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"mineCard": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 2 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for mining the active card. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"quitMpv": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 6 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for quitting mpv. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"previousAudio": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor for previous Yomitan audio. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"nextAudio": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 5 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for next Yomitan audio. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"playCurrentAudio": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 4 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for playing the current Yomitan audio. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"toggleMpvPause": {
|
||
"kind": "button", // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
"buttonIndex": 9 // Raw button index captured for this discrete controller action.
|
||
}, // Controller binding descriptor for toggling mpv play/pause. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"holdSecondarySub": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that shows the secondary subtitle only while held. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"previousEntry": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that selects the previous word entry in the open Yomitan popup. Mine Card mines the selected entry. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"nextEntry": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that selects the next word entry in the open Yomitan popup. Mine Card mines the selected entry. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"previousSubtitle": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that jumps to the previous subtitle line, like Shift+H. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"nextSubtitle": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that jumps to the next subtitle line, like Shift+L. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"replaySubtitle": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that replays the current subtitle line, then pauses, like Ctrl+Shift+H. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"playNextSubtitle": {
|
||
"kind": "none" // Discrete binding input source kind. When kind is "axis", set both axisIndex and direction. Values: none | button | axis
|
||
}, // Controller binding descriptor that plays the next subtitle line, then pauses, like Ctrl+Shift+L. Works with or without keyboard-only mode. Use Alt+C learn mode or set a raw button/axis descriptor manually. If kind is "axis", direction is required.
|
||
"leftStickHorizontal": {
|
||
"kind": "axis", // Analog binding input source kind. Values: none | axis
|
||
"axisIndex": 0, // Raw axis index captured for this analog controller action.
|
||
"dpadFallback": "horizontal" // Optional D-pad fallback used when this analog controller action should also read D-pad input. Values: none | horizontal | vertical
|
||
}, // Axis binding descriptor used for left/right token selection. Use Alt+C learn mode or set a raw axis descriptor manually.
|
||
"leftStickVertical": {
|
||
"kind": "axis", // Analog binding input source kind. Values: none | axis
|
||
"axisIndex": 1, // Raw axis index captured for this analog controller action.
|
||
"dpadFallback": "vertical" // Optional D-pad fallback used when this analog controller action should also read D-pad input. Values: none | horizontal | vertical
|
||
}, // Axis binding descriptor used for primary popup scrolling. Use Alt+C learn mode or set a raw axis descriptor manually.
|
||
"rightStickHorizontal": {
|
||
"kind": "axis", // Analog binding input source kind. Values: none | axis
|
||
"axisIndex": 3, // Raw axis index captured for this analog controller action.
|
||
"dpadFallback": "none" // Optional D-pad fallback used when this analog controller action should also read D-pad input. Values: none | horizontal | vertical
|
||
}, // Axis binding descriptor reserved for alternate right-stick mappings. Use Alt+C learn mode or set a raw axis descriptor manually.
|
||
"rightStickVertical": {
|
||
"kind": "axis", // Analog binding input source kind. Values: none | axis
|
||
"axisIndex": 4, // Raw axis index captured for this analog controller action.
|
||
"dpadFallback": "none" // Optional D-pad fallback used when this analog controller action should also read D-pad input. Values: none | horizontal | vertical
|
||
} // Axis binding descriptor used for popup page jumps. Use Alt+C learn mode or set a raw axis descriptor manually.
|
||
}, // Raw controller binding descriptors saved by Alt+C learn mode. For discrete axis bindings, kind "axis" requires axisIndex and direction.
|
||
"reviewBindings": {
|
||
"confirm": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "a" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Use this timing.
|
||
"cancel": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "b" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Cancel.
|
||
"play": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "x" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Play selection.
|
||
"resetTiming": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "y" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Reset timing.
|
||
"showEarlier": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "left" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Earlier −2s. Repeats while held.
|
||
"showLater": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "right" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Later +2s. Repeats while held.
|
||
"framePrevious": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "up" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Previous screenshot frame. Repeats while held.
|
||
"frameNext": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "down" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Next screenshot frame. Repeats while held.
|
||
"frameReset": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 5 // Raw button index.
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 4 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Reset screenshot frame.
|
||
"startBack": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "left" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 4 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Start −0.1s. Repeats while held.
|
||
"startForward": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "right" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 4 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Start +0.1s. Repeats while held.
|
||
"previousLineAdd": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "up" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 4 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Add previous line. Repeats while held.
|
||
"previousLineRemove": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "down" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 4 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Remove previous line. Repeats while held.
|
||
"endBack": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "left" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 5 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: End −0.1s. Repeats while held.
|
||
"endForward": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "right" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 5 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: End +0.1s. Repeats while held.
|
||
"nextLineAdd": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "up" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 5 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Add next line. Repeats while held.
|
||
"nextLineRemove": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "down" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": {
|
||
"kind": "button", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"buttonIndex": 5 // Raw button index.
|
||
} // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Remove next line. Repeats while held.
|
||
"useOriginal": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "a" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Use original timing (after cancel).
|
||
"keepEditing": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "b" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Keep editing (after cancel).
|
||
"skipMedia": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "x" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Review dialog: Without media (after cancel).
|
||
"discard": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "y" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
} // Review dialog: Discard card (after cancel).
|
||
}, // Controller layout for the media timing review dialog, one entry per action. Set it with the Review media timing group in Alt+C. Each entry is {"kind": "none"} or {"press": input, "hold": input}, where an input is {"kind": "button", "buttonIndex"}, {"kind": "axis", "axisIndex", "direction"}, {"kind": "face", "letter": "a"|"b"|"x"|"y"} (printed letter) or {"kind": "dpad", "direction": "left"|"right"|"up"|"down"}.
|
||
"fieldGroupingBindings": {
|
||
"selectOriginal": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "left" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Original card.
|
||
"selectNew": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "right" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: New card.
|
||
"toggleDeleteDuplicate": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "x" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Delete duplicate on/off.
|
||
"continue": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "a" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Continue.
|
||
"cancel": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "b" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Cancel.
|
||
"confirmMerge": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "a" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Confirm merge (merge preview).
|
||
"back": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "b" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Back (merge preview).
|
||
"cancelMerge": {
|
||
"kind": "none" // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
}, // Duplicate card dialog: Cancel (merge preview).
|
||
"toggleView": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "face", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"letter": "y" // Printed face letter, placed by controller.faceButtonLabels. Values: a | b | x | y
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Compact / Full (merge preview).
|
||
"scrollUp": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "up" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
}, // Duplicate card dialog: Scroll up (merge preview). Repeats while held.
|
||
"scrollDown": {
|
||
"kind": "combo", // none disables the action; combo presses "press" (while holding "hold", if set). Values: none | combo
|
||
"press": {
|
||
"kind": "dpad", // Input kind: a raw button or axis recorded by Alt+C, a printed face letter, or a D-pad direction. Values: button | axis | face | dpad
|
||
"direction": "down" // D-pad direction, or axis direction for raw axis inputs. Values: left | right | up | down | negative | positive
|
||
}, // Input that triggers the action.
|
||
"hold": null // Optional input held while pressing; null for none.
|
||
} // Duplicate card dialog: Scroll down (merge preview). Repeats while held.
|
||
}, // Controller layout for the duplicate card (field grouping) dialog, one entry per action. Set it with the Duplicate card (field grouping) group in Alt+C. Each entry is {"kind": "none"} or {"press": input, "hold": input}, where an input is {"kind": "button", "buttonIndex"}, {"kind": "axis", "axisIndex", "direction"}, {"kind": "face", "letter": "a"|"b"|"x"|"y"} (printed letter) or {"kind": "dpad", "direction": "left"|"right"|"up"|"down"}.
|
||
"profiles": {} // Per-controller binding and button-index overrides keyed by the controller id reported by the Gamepad API.
|
||
}, // Gamepad support for the visible overlay while keyboard-only mode is active.
|
||
|
||
// ==========================================
|
||
// Startup Warmups
|
||
// Background warmup controls for MeCab, Yomitan, dictionaries, and Jellyfin session.
|
||
// Disable individual warmups to defer load until first real usage.
|
||
// lowPowerMode defers all warmups except Yomitan extension.
|
||
// ==========================================
|
||
"startupWarmups": {
|
||
"lowPowerMode": false, // Defer startup warmups except Yomitan extension. Values: true | false
|
||
"mecab": true, // Warm up MeCab tokenizer at startup. Values: true | false
|
||
"yomitanExtension": true, // Warm up Yomitan extension at startup. Values: true | false
|
||
"subtitleDictionaries": true, // Warm up subtitle dictionaries at startup. Values: true | false
|
||
"jellyfinRemoteSession": false // Warm up Jellyfin remote session at startup. Values: true | false
|
||
}, // Background warmup controls for MeCab, Yomitan, dictionaries, and Jellyfin session.
|
||
|
||
// ==========================================
|
||
// Updates
|
||
// Automatic update check behavior.
|
||
// Manual checks from the tray or launcher are always allowed.
|
||
// ==========================================
|
||
"updates": {
|
||
"enabled": true, // Run automatic update checks in the background. Values: true | false
|
||
"checkIntervalHours": 24, // Minimum hours between automatic update checks.
|
||
"notificationType": "overlay", // How SubMiner announces available updates. overlay shows notifications on the overlay, system uses OS notifications, both uses overlay and system. osd and osd-system are legacy config-file-only values. Values: overlay | system | both | none | osd | osd-system
|
||
"channel": "stable" // Release channel used for update checks. Values: stable | prerelease
|
||
}, // Automatic update check behavior.
|
||
|
||
// ==========================================
|
||
// Notifications
|
||
// Overlay notification display behavior.
|
||
// Hot-reload: position changes apply to the next overlay notification.
|
||
// ==========================================
|
||
"notifications": {
|
||
"overlayPosition": "top-right" // Position for in-overlay notification cards. Values: top-left | top | top-right
|
||
}, // Overlay notification display behavior.
|
||
|
||
// ==========================================
|
||
// Plugins
|
||
// JavaScript plugins loaded from <config dir>/plugins/<id>/ at startup.
|
||
// Plugins run inside SubMiner with full access to your system. Only enable code you trust.
|
||
// Restart SubMiner after changing plugins.
|
||
// ==========================================
|
||
"plugins": {}, // Plugins to load at startup, keyed by directory name under <config dir>/plugins/. Each entry is { "enabled": true, "settings": { ... } }; settings are passed to the plugin as ctx.settings.
|
||
|
||
// ==========================================
|
||
// Keyboard Shortcuts
|
||
// Overlay keyboard shortcuts. Set a shortcut to null to disable.
|
||
// Hot-reload: shortcut changes apply live and update the session help modal on reopen.
|
||
// ==========================================
|
||
"shortcuts": {
|
||
"toggleVisibleOverlayGlobal": "Alt+Shift+O", // Global accelerator that toggles overlay visibility from anywhere on the system. Use null to disable.
|
||
"copySubtitle": "CommandOrControl+C", // Accelerator that copies the current subtitle line to the clipboard.
|
||
"copySubtitleMultiple": "CommandOrControl+Shift+C", // Accelerator that copies consecutive subtitle lines while the multi-copy window stays open.
|
||
"updateLastCardFromClipboard": "CommandOrControl+V", // Accelerator that updates the last mined Anki card using the current clipboard contents.
|
||
"triggerFieldGrouping": "CommandOrControl+G", // Accelerator that triggers Kiku field grouping on duplicate cards.
|
||
"triggerSubsync": "Ctrl+Alt+S", // Accelerator that triggers subsync against the active subtitle file.
|
||
"mineSentence": "CommandOrControl+S", // Accelerator that mines the current sentence as a new Anki card.
|
||
"mineSentenceMultiple": "CommandOrControl+Shift+S", // Accelerator that mines consecutive sentences while the multi-mine window stays open.
|
||
"multiCopyTimeoutMs": 3000, // Timeout for multi-copy/mine modes.
|
||
"toggleSecondarySub": "CommandOrControl+Shift+V", // Accelerator that toggles the secondary subtitle bar visibility.
|
||
"markAudioCard": "CommandOrControl+Shift+A", // Accelerator that marks the last mined card as an audio card.
|
||
"openCharacterDictionaryManager": "CommandOrControl+D", // Accelerator that opens the character dictionary manager modal.
|
||
"openRuntimeOptions": "CommandOrControl+Shift+O", // Accelerator that opens the runtime options modal.
|
||
"openJimaku": "Ctrl+Shift+J", // Accelerator that opens the Jimaku subtitle search modal.
|
||
"openTsukihime": "Ctrl+Shift+T", // Accelerator that opens the TsukiHime subtitle search modal (configured secondary/Japanese primary tabs).
|
||
"openSubtitleSelection": "g-s", // Open subtitle selection when enabled. Use g-s to press g then s. Set null to unbind.
|
||
"openSubtitleGeneration": "Ctrl+Shift+G", // Accelerator that opens the standalone Japanese subtitle generation modal.
|
||
"openSessionHelp": "CommandOrControl+Slash", // Accelerator that opens the session help / keybinding cheatsheet.
|
||
"openControllerSelect": "Alt+C", // Accelerator that opens the controller selection and learn-mode modal.
|
||
"openControllerDebug": "Alt+Shift+C", // Accelerator that opens the controller debug modal with live axis/button readouts.
|
||
"toggleSubtitleSidebar": "Backslash", // Accelerator that toggles the subtitle sidebar visibility.
|
||
"toggleNotificationHistory": "CommandOrControl+N", // Accelerator that toggles the overlay notification history panel.
|
||
"appendClipboardVideoToQueue": "CommandOrControl+A" // Accelerator that appends a video path from the clipboard to the mpv playlist.
|
||
}, // Overlay keyboard shortcuts. Set a shortcut to null to disable.
|
||
|
||
// ==========================================
|
||
// Keybindings (MPV Commands)
|
||
// Default and custom keybindings that are merged with built-in defaults.
|
||
// Set command to null to disable a default keybinding.
|
||
// Hot-reload: keybinding changes apply live and update the session help modal on reopen.
|
||
// ==========================================
|
||
"keybindings": [
|
||
{
|
||
"key": "Space", // Key setting.
|
||
"command": [
|
||
"cycle",
|
||
"pause"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "KeyF", // Key setting.
|
||
"command": [
|
||
"cycle",
|
||
"fullscreen"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "KeyJ", // Key setting.
|
||
"command": [
|
||
"cycle",
|
||
"sid"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Shift+KeyJ", // Key setting.
|
||
"command": [
|
||
"cycle",
|
||
"secondary-sid"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "ArrowRight", // Key setting.
|
||
"command": [
|
||
"seek",
|
||
5
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "ArrowLeft", // Key setting.
|
||
"command": [
|
||
"seek",
|
||
-5
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "ArrowUp", // Key setting.
|
||
"command": [
|
||
"seek",
|
||
60
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "ArrowDown", // Key setting.
|
||
"command": [
|
||
"seek",
|
||
-60
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Shift+KeyH", // Key setting.
|
||
"command": [
|
||
"sub-seek",
|
||
-1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Shift+KeyL", // Key setting.
|
||
"command": [
|
||
"sub-seek",
|
||
1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Shift+ArrowLeft", // Key setting.
|
||
"command": [
|
||
"sub-step",
|
||
-1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Shift+ArrowRight", // Key setting.
|
||
"command": [
|
||
"sub-step",
|
||
1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "KeyZ", // Key setting.
|
||
"command": [
|
||
"add",
|
||
"sub-delay",
|
||
-0.1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Shift+KeyZ", // Key setting.
|
||
"command": [
|
||
"add",
|
||
"sub-delay",
|
||
0.1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "KeyX", // Key setting.
|
||
"command": [
|
||
"add",
|
||
"sub-delay",
|
||
0.1
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Alt+KeyC", // Key setting.
|
||
"command": [
|
||
"__youtube-picker-open"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Alt+KeyP", // Key setting.
|
||
"command": [
|
||
"__playlist-browser-open"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Shift+KeyH", // Key setting.
|
||
"command": [
|
||
"__replay-subtitle"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+Shift+KeyL", // Key setting.
|
||
"command": [
|
||
"__play-next-subtitle"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "KeyQ", // Key setting.
|
||
"command": [
|
||
"quit"
|
||
] // Command setting.
|
||
},
|
||
{
|
||
"key": "Ctrl+KeyW", // Key setting.
|
||
"command": [
|
||
"quit"
|
||
] // Command setting.
|
||
}
|
||
], // Default and custom keybindings that are merged with built-in defaults.
|
||
|
||
// ==========================================
|
||
// Secondary Subtitles
|
||
// Dual subtitle track options.
|
||
// Used by managed subtitle loading as secondary language preferences for local and YouTube playback.
|
||
// Hot-reload: defaultMode updates live while SubMiner is running.
|
||
// ==========================================
|
||
"secondarySub": {
|
||
"secondarySubLanguages": [], // Language code priority list used to auto-select a secondary subtitle track when available.
|
||
"autoLoadSecondarySub": false, // Automatically load a matching secondary subtitle when the primary subtitle loads. Values: true | false
|
||
"defaultMode": "hover" // Default visibility mode for the secondary subtitle bar. Values: hidden | visible | hover
|
||
}, // Dual subtitle track options.
|
||
|
||
// ==========================================
|
||
// Subtitle Sync
|
||
// Subsync engine and executable paths.
|
||
// Hot-reload: subsync changes apply to the next subtitle sync run.
|
||
// ==========================================
|
||
"subsync": {
|
||
"alass_path": "", // Optional absolute path to the alass binary used by subsync. Leave empty to auto-discover from PATH.
|
||
"ffsubsync_path": "", // Optional absolute path to the ffsubsync binary used by subsync. Leave empty to auto-discover from PATH.
|
||
"ffmpeg_path": "", // Optional absolute path to the ffmpeg binary used by subsync. Leave empty to auto-discover from PATH.
|
||
"replace": true // Replace the active subtitle file when sync completes. Values: true | false
|
||
}, // Subsync engine and executable paths.
|
||
|
||
// ==========================================
|
||
// Subtitle Position
|
||
// Initial vertical subtitle position from the bottom.
|
||
// ==========================================
|
||
"subtitlePosition": {
|
||
"yPercent": 10 // Vertical position of the subtitle overlay expressed as a percentage from the bottom of the screen.
|
||
}, // Initial vertical subtitle position from the bottom.
|
||
|
||
// ==========================================
|
||
// Subtitle Appearance
|
||
// Primary and secondary subtitle styling.
|
||
// Hot-reload: subtitle style changes apply live without restarting SubMiner.
|
||
// ==========================================
|
||
"subtitleStyle": {
|
||
"primaryDefaultMode": "visible", // Default primary subtitle bar visibility mode. hidden hides it, visible shows it, hover reveals it on hover. Values: hidden | visible | hover
|
||
"css": {
|
||
"font-family": "Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP", // Font family setting.
|
||
"color": "#cad3f5", // Color setting.
|
||
"background-color": "transparent", // Background color setting.
|
||
"font-size": "35px", // Font size setting.
|
||
"font-weight": "600", // Font weight setting.
|
||
"font-style": "normal", // Font style setting.
|
||
"line-height": "1.35", // Line height setting.
|
||
"letter-spacing": "-0.01em", // Letter spacing setting.
|
||
"word-spacing": "0", // Word spacing setting.
|
||
"font-kerning": "normal", // Font kerning setting.
|
||
"text-rendering": "geometricPrecision", // Text rendering setting.
|
||
"text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)", // Text shadow setting.
|
||
"backdrop-filter": "blur(6px)", // Backdrop filter setting.
|
||
"--subtitle-hover-token-color": "#f4dbd6", // Subtitle hover token color setting.
|
||
"--subtitle-hover-token-background-color": "transparent" // Subtitle hover token background color setting.
|
||
}, // CSS declaration object applied to primary subtitles after normal subtitle style defaults.
|
||
"enableJlpt": false, // Enable JLPT vocabulary level underlines. When disabled, JLPT tagging lookup and underlines are skipped. Values: true | false
|
||
"preserveLineBreaks": false, // Preserve line breaks in visible overlay subtitle rendering. When false, line breaks are flattened to spaces for a single-line flow. Values: true | false
|
||
"autoPauseVideoOnHover": true, // Automatically pause mpv playback while hovering subtitle text, then resume on leave. Values: true | false
|
||
"autoPauseVideoOnYomitanPopup": true, // Automatically pause mpv playback while Yomitan popup is open, then resume when popup closes. Values: true | false
|
||
"autoPauseVideoOnKeyboardMode": false, // Pause mpv when keyboard-only mode turns on (from the keyboard or a controller) and resume when it turns off. Leaving the mode resumes only a pause it made: a video that was already paused, or that you played or paused yourself meanwhile, is left as it is. Values: true | false
|
||
"primaryVisibleOnYomitanPopup": true, // Keep the primary subtitle bar visible while a Yomitan popup is open when primary subtitles are in hover mode. Values: true | false
|
||
"nameMatchEnabled": false, // Enable character dictionary sync and subtitle token coloring for character-name matches. Values: true | false
|
||
"nameMatchImagesEnabled": false, // Show small character portraits beside subtitle tokens matched from the SubMiner character dictionary. Values: true | false
|
||
"nameMatchColor": "#f5bde6", // Hex color used when a subtitle token matches an entry from the SubMiner character dictionary.
|
||
"nPlusOneColor": "#c6a0f6", // Color used for the single N+1 target token subtitle highlight.
|
||
"knownWordColor": "#a6da95", // Color used for known-word subtitle highlights.
|
||
"knownWordMaturityColors": {
|
||
"new": "#ee99a0", // Color for known words whose Anki cards are new (never reviewed), when maturity highlighting is enabled.
|
||
"learning": "#b7bdf8", // Color for known words whose Anki cards are in (re)learning, when maturity highlighting is enabled.
|
||
"young": "#91d7e3", // Color for known words whose Anki cards are in review below the mature threshold, when maturity highlighting is enabled.
|
||
"mature": "#a6da95" // Color for known words whose Anki cards are at or above the mature interval threshold, when maturity highlighting is enabled.
|
||
}, // Known word maturity colors setting.
|
||
"jlptColors": {
|
||
"N1": "#ed8796", // N1 setting.
|
||
"N2": "#f5a97f", // N2 setting.
|
||
"N3": "#f9e2af", // N3 setting.
|
||
"N4": "#8bd5ca", // N4 setting.
|
||
"N5": "#8aadf4" // N5 setting.
|
||
}, // Jlpt colors setting.
|
||
"frequencyDictionary": {
|
||
"enabled": false, // Enable frequency-dictionary-based highlighting based on token rank. Values: true | false
|
||
"sourcePath": "", // Optional absolute path to a frequency dictionary directory. If empty, built-in discovery search paths are used.
|
||
"topX": 10000, // Only color tokens with frequency rank <= topX (default: 10000).
|
||
"mode": "single", // single: use one color for all matching tokens. banded: use color ramp by frequency band. Values: single | banded
|
||
"matchMode": "headword", // headword: frequency lookup uses dictionary form. surface: lookup uses subtitle-visible token text. Values: headword | surface
|
||
"singleColor": "#f5a97f", // Color used when frequencyDictionary.mode is `single`.
|
||
"bandedColors": [
|
||
"#ed8796",
|
||
"#f5a97f",
|
||
"#f9e2af",
|
||
"#8bd5ca",
|
||
"#8aadf4"
|
||
] // Five colors used for rank bands when mode is `banded` (from most common to least within topX).
|
||
}, // Frequency dictionary setting.
|
||
"secondary": {
|
||
"css": {
|
||
"font-family": "Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP", // Font family setting.
|
||
"color": "#cad3f5", // Color setting.
|
||
"background-color": "transparent", // Background color setting.
|
||
"font-size": "24px", // Font size setting.
|
||
"font-weight": "600", // Font weight setting.
|
||
"font-style": "normal", // Font style setting.
|
||
"line-height": "1.35", // Line height setting.
|
||
"letter-spacing": "-0.01em", // Letter spacing setting.
|
||
"word-spacing": "0", // Word spacing setting.
|
||
"font-kerning": "normal", // Font kerning setting.
|
||
"text-rendering": "geometricPrecision", // Text rendering setting.
|
||
"text-shadow": "-1px -1px 2px rgba(0,0,0,0.95), 1px -1px 2px rgba(0,0,0,0.95), -1px 1px 2px rgba(0,0,0,0.95), 1px 1px 2px rgba(0,0,0,0.95), 0 0 8px rgba(0,0,0,0.5)", // Text shadow setting.
|
||
"backdrop-filter": "blur(6px)" // Backdrop filter setting.
|
||
} // CSS declaration object applied to secondary subtitles after normal subtitle style defaults.
|
||
} // Secondary setting.
|
||
}, // Primary and secondary subtitle styling.
|
||
|
||
// ==========================================
|
||
// Subtitle Sidebar
|
||
// Parsed-subtitle sidebar cue list styling, behavior, and toggle key.
|
||
// Hot-reload: subtitle sidebar changes apply live without restarting SubMiner.
|
||
// ==========================================
|
||
"subtitleSidebar": {
|
||
"enabled": true, // Enable the subtitle sidebar feature for parsed subtitle sources. Values: true | false
|
||
"autoOpen": false, // Automatically open the subtitle sidebar once during overlay startup. Values: true | false
|
||
"layout": "overlay", // Render the subtitle sidebar as a floating overlay or reserve space inside mpv. Values: overlay | embedded
|
||
"toggleKey": "Backslash", // KeyboardEvent.code used to toggle the subtitle sidebar open and closed.
|
||
"pauseVideoOnHover": true, // Pause mpv while hovering the subtitle sidebar, then resume on leave. Values: true | false
|
||
"autoScroll": true, // Auto-scroll the active subtitle cue into view while playback advances. Values: true | false
|
||
"css": {
|
||
"font-family": "Hiragino Sans, M PLUS 1, Source Han Sans JP, Noto Sans CJK JP", // Font family setting.
|
||
"color": "#cad3f5", // Color setting.
|
||
"background-color": "rgba(73, 77, 100, 0.9)", // Background color setting.
|
||
"font-size": "16px", // Font size setting.
|
||
"opacity": "0.95", // Opacity setting.
|
||
"--subtitle-sidebar-max-width": "420px", // Subtitle sidebar max width setting.
|
||
"--subtitle-sidebar-timestamp-color": "#a5adcb", // Subtitle sidebar timestamp color setting.
|
||
"--subtitle-sidebar-active-line-color": "#f5bde6", // Subtitle sidebar active line color setting.
|
||
"--subtitle-sidebar-active-background-color": "rgba(138, 173, 244, 0.22)", // Subtitle sidebar active background color setting.
|
||
"--subtitle-sidebar-hover-background-color": "rgba(54, 58, 79, 0.84)" // Subtitle sidebar hover background color setting.
|
||
} // CSS declaration object applied to the subtitle sidebar. Includes color, background-color, and all font properties.
|
||
}, // Parsed-subtitle sidebar cue list styling, behavior, and toggle key.
|
||
|
||
// ==========================================
|
||
// Shared AI Provider
|
||
// Canonical OpenAI-compatible provider transport settings shared by Anki and YouTube subtitle fixing.
|
||
// ==========================================
|
||
"ai": {
|
||
"enabled": false, // Enable shared OpenAI-compatible AI provider features. Values: true | false
|
||
"apiKey": "", // Static API key for the shared OpenAI-compatible AI provider.
|
||
"apiKeyCommand": "", // Shell command used to resolve the shared AI provider API key.
|
||
"model": "openai/gpt-4o-mini", // Default model identifier requested from the shared AI provider.
|
||
"baseUrl": "https://openrouter.ai/api", // Base URL for the shared OpenAI-compatible AI provider.
|
||
"systemPrompt": "You are a translation engine. Return only the translated text with no explanations.", // Default system prompt sent with shared AI provider requests.
|
||
"requestTimeoutMs": 15000 // Timeout in milliseconds for shared AI provider requests.
|
||
}, // Canonical OpenAI-compatible provider transport settings shared by Anki and YouTube subtitle fixing.
|
||
|
||
// ==========================================
|
||
// AnkiConnect Integration
|
||
// Automatic Anki updates and media generation options.
|
||
// Hot-reload: ankiConnect.ai.enabled, media.normalizeAudio/mirrorMpvVolume/reviewTiming, knownWords, nPlusOne, fields.word/audio/wordAudio/image/sentence/miscInfo, behavior.autoUpdateNewCards, isLapis.sentenceCardModel, isKiku.fieldGrouping, isSenren.fieldGrouping, and lapisKiku.wordCardKind update live while SubMiner is running.
|
||
// Shared AI provider transport settings are read from top-level ai and typically require restart.
|
||
// Most other AnkiConnect settings still require restart.
|
||
// ==========================================
|
||
"ankiConnect": {
|
||
"enabled": true, // Enable AnkiConnect integration. Values: true | false
|
||
"url": "http://127.0.0.1:8765", // Base URL of the AnkiConnect HTTP server.
|
||
"pollingRate": 3000, // Polling interval in milliseconds.
|
||
"proxy": {
|
||
"enabled": true, // Enable local AnkiConnect-compatible proxy for push-based auto-enrichment. Values: true | false
|
||
"host": "127.0.0.1", // Bind host for local AnkiConnect proxy.
|
||
"port": 8766, // Bind port for local AnkiConnect proxy.
|
||
"upstreamUrl": "http://127.0.0.1:8765" // Upstream AnkiConnect URL proxied by local AnkiConnect proxy.
|
||
}, // Proxy setting.
|
||
"tags": [
|
||
"SubMiner"
|
||
], // Tags to add to cards mined or updated by SubMiner. Provide an empty array to disable automatic tagging.
|
||
"deck": "", // Restrict duplicate detection and card enrichment to this Anki deck. Leave empty to use the Yomitan mining deck when available.
|
||
"fields": {
|
||
"word": "Expression", // Card field for the mined word or expression text.
|
||
"audio": "SentenceAudio", // Card field that receives generated sentence audio.
|
||
"wordAudio": "ExpressionAudio", // Existing word-audio field read to time the frozen first frame of animated images. This mapping is only used for synchronization.
|
||
"image": "Picture", // Card field that receives the captured screenshot or animated image.
|
||
"sentence": "Sentence", // Card field that receives the source sentence text.
|
||
"miscInfo": "MiscInfo", // Card field that receives the miscellaneous info pattern (see ankiConnect.metadata.pattern).
|
||
"translation": "SelectionText" // Card field that receives the current selection or translated text.
|
||
}, // Fields setting.
|
||
"ai": {
|
||
"enabled": false, // Enable AI provider usage for Anki translation/enrichment flows. Values: true | false
|
||
"model": "", // Optional model override for Anki AI translation/enrichment flows.
|
||
"systemPrompt": "" // Optional system prompt override for Anki AI translation/enrichment flows.
|
||
}, // Ai setting.
|
||
"media": {
|
||
"generateAudio": true, // Generate sentence audio for mined cards. Values: true | false
|
||
"generateImage": true, // Generate screenshot or animated image for mined cards. Values: true | false
|
||
"imageType": "static", // Image capture type: "static" for a single still frame, "avif" for an animated AVIF. Values: static | avif
|
||
"imageFormat": "jpg", // Encoding format used when imageType is "static". Values: jpg | png | webp
|
||
"imageQuality": 92, // Quality (0-100) used for lossy static image encoders.
|
||
"imageMaxWidth": 0, // Maximum width for static images, in pixels. Set to 0 to preserve the source resolution.
|
||
"imageMaxHeight": 0, // Maximum height for static images, in pixels. Set to 0 to preserve the source resolution.
|
||
"animatedFps": 10, // Target frame rate for animated AVIF captures.
|
||
"animatedMaxWidth": 640, // Maximum width applied to animated AVIF captures.
|
||
"animatedMaxHeight": 0, // Maximum height for animated AVIF captures, in pixels. Set to 0 to preserve aspect ratio.
|
||
"animatedCrf": 35, // Animated AVIF CRF quality target. Lower values produce larger, higher-quality files.
|
||
"syncAnimatedImageToWordAudio": true, // For animated AVIF images, prepend a frozen first frame matching the existing word-audio duration so motion starts with sentence audio. Values: true | false
|
||
"normalizeAudio": true, // Normalize generated sentence audio loudness during media extraction. Changes apply live. Values: true | false
|
||
"mirrorMpvVolume": true, // Apply mpv's current software volume curve to generated sentence audio. Changes apply live. Values: true | false
|
||
"reviewTiming": false, // Review and preview subtitle media timing before SubMiner creates or enriches a mined card. Values: true | false
|
||
"audioPadding": 0, // Seconds of padding appended to both ends of generated sentence audio and animated AVIF clips.
|
||
"fallbackDuration": 3, // Fallback clip duration in seconds when subtitle timing data is unavailable.
|
||
"maxMediaDuration": 30 // Maximum allowed media clip duration in seconds. 0 disables the cap.
|
||
}, // Media setting.
|
||
"knownWords": {
|
||
"highlightEnabled": false, // Enable fast local highlighting for words already known in Anki. Values: true | false
|
||
"maturityEnabled": false, // Color known-word highlights by Anki card maturity (new, learning, young, mature) instead of a single color. Requires known-word highlighting. Values: true | false
|
||
"matureThresholdDays": 21, // Card interval in days at which a known word counts as mature (Anki convention: 21).
|
||
"refreshMinutes": 1440, // Minutes between known-word cache refreshes.
|
||
"addMinedWordsImmediately": true, // Immediately append newly mined card words into the known-word cache. Values: true | false
|
||
"matchMode": "headword", // Known-word matching strategy for subtitle annotations. Cache matches always receive known-word highlighting even when POS filters suppress other annotation types. Values: headword | surface
|
||
"decks": {} // Decks and expression/word fields for known-word cache. Object mapping deck names to arrays of field names to extract, e.g. { "Kaishi 1.5k": ["Word"] }. Reading fields (Reading, Word Reading, ExpressionReading) are always probed so cached words match only in the reading their note teaches; words from notes without readings match in any reading.
|
||
}, // Known words setting.
|
||
"behavior": {
|
||
"overwriteAudio": true, // When updating an existing card, overwrite the audio field instead of skipping it. Values: true | false
|
||
"overwriteImage": true, // When updating an existing card, overwrite the image field instead of skipping it. Values: true | false
|
||
"mediaInsertMode": "append", // Whether new media is appended after or prepended before existing field contents on update. Values: append | prepend
|
||
"highlightWord": true, // Bold the mined word inside the sentence field on the saved Anki card. Values: true | false
|
||
"notificationType": "overlay", // Notification surface used to announce mining and update outcomes. overlay shows notifications on the overlay, system uses OS notifications, both uses overlay and system. osd and osd-system are legacy config-file-only values. Values: overlay | system | both | none | osd | osd-system
|
||
"autoUpdateNewCards": true // Automatically update newly added cards. Values: true | false
|
||
}, // Behavior setting.
|
||
"nPlusOne": {
|
||
"enabled": false, // Enable N+1 subtitle highlighting (highlights the one unknown word in a sentence). Requires known-word cache data. Values: true | false
|
||
"minSentenceWords": 3 // Minimum sentence word count required for N+1 targeting (default: 3).
|
||
}, // N plus one setting.
|
||
"metadata": {
|
||
"pattern": "[SubMiner] %f (%t)" // Template used to render the miscInfo field. Placeholders include %f (filename) and %t (timestamp).
|
||
}, // Metadata setting.
|
||
"isLapis": {
|
||
"enabled": false, // Enable Lapis-specific mining behaviors and sentence card model targeting. Values: true | false
|
||
"sentenceCardModel": "Lapis" // Note type name used by Lapis sentence cards.
|
||
}, // Is lapis setting.
|
||
"isKiku": {
|
||
"enabled": false, // Enable Kiku-specific mining behaviors (duplicate handling, field grouping). Values: true | false
|
||
"fieldGrouping": "disabled", // Kiku duplicate-card field grouping mode. Values: auto | manual | disabled
|
||
"deleteDuplicateInAuto": true // When Kiku field grouping is "auto", delete the duplicate source card after grouping completes. Values: true | false
|
||
}, // Is kiku setting.
|
||
"isSenren": {
|
||
"enabled": false, // Enable Senren-specific duplicate handling (scene-switching field grouping, including miscInfo grouping). Mutually exclusive with isKiku.enabled. Values: true | false
|
||
"fieldGrouping": "auto", // Senren duplicate-card field grouping mode (scene switching). Values: auto | manual | disabled
|
||
"deleteDuplicateInAuto": true // When Senren field grouping is "auto", delete the duplicate source card after grouping completes. Values: true | false
|
||
}, // Is senren setting.
|
||
"lapisKiku": {
|
||
"wordCardKind": "word-and-sentence" // Card-type flag SubMiner marks on Kiku/Lapis word cards. Only one flag is set at a time; the others are cleared. Requires isKiku.enabled or isLapis.enabled. Values: word-and-sentence | click | sentence | audio | none
|
||
} // Lapis kiku setting.
|
||
}, // Automatic Anki updates and media generation options.
|
||
|
||
// ==========================================
|
||
// Jimaku
|
||
// Jimaku API configuration and defaults.
|
||
// Hot-reload: Jimaku changes apply to the next Jimaku request.
|
||
// ==========================================
|
||
"jimaku": {
|
||
"apiBaseUrl": "https://jimaku.cc", // Base URL of the Jimaku subtitle search API.
|
||
"apiKey": "", // Jimaku API key. Optional but recommended for higher rate limits. Get one for free at https://jimaku.cc.
|
||
"apiKeyCommand": "", // Shell command that prints the Jimaku API key to stdout. Used instead of apiKey to avoid storing the key in plain text.
|
||
"languagePreference": "ja", // Preferred language used in Jimaku search. Values: ja | en | none
|
||
"maxEntryResults": 10 // Maximum Jimaku search results returned.
|
||
}, // Jimaku API configuration and defaults.
|
||
|
||
// ==========================================
|
||
// TsukiHime
|
||
// TsukiHime subtitle search configuration for Japanese primary and configured secondary subtitles. No API key required.
|
||
// Hot-reload: TsukiHime changes apply to the next TsukiHime request.
|
||
// ==========================================
|
||
"tsukihime": {
|
||
"apiBaseUrl": "https://api.tsukihime.org/v1", // Base URL of the TsukiHime API (Animetosho successor). No API key required.
|
||
"maxSearchResults": 10 // Maximum TsukiHime search results returned.
|
||
}, // TsukiHime subtitle search configuration for Japanese primary and configured secondary subtitles. No API key required.
|
||
|
||
// ==========================================
|
||
// TMDB
|
||
// TMDB (The Movie Database) metadata for live-action dramas and movies in the stats Library: posters, synopses, and grouping by show.
|
||
// Hot-reload: TMDB changes apply to the next TMDB request.
|
||
// ==========================================
|
||
"tmdb": {
|
||
"apiKey": "", // Your own TMDB API key or read access token for live-action posters and synopses in the stats Library. Release builds bundle a project key, so set this only to use your own quota or when running from source (free under Settings > API on themoviedb.org).
|
||
"apiKeyCommand": "" // Shell command that prints the TMDB API key to stdout. Used instead of apiKey to avoid storing the key in plain text.
|
||
}, // TMDB (The Movie Database) metadata for live-action dramas and movies in the stats Library: posters, synopses, and grouping by show.
|
||
|
||
// ==========================================
|
||
// YouTube Playback Settings
|
||
// Defaults for managed subtitle language preferences and YouTube subtitle loading.
|
||
// Hot-reload: primarySubLanguages and subtitleSource apply to the next YouTube subtitle load.
|
||
// ==========================================
|
||
"youtube": {
|
||
"primarySubLanguages": [
|
||
"ja",
|
||
"jpn"
|
||
], // Comma-separated primary subtitle language priority for managed subtitle auto-selection.
|
||
"subtitleSource": "youtube", // Where primary YouTube subtitles come from. Whisper transcribes the audio locally using the subtitleGeneration settings. Values: youtube | whisper
|
||
"mediaCache": {
|
||
"mode": "direct", // How YouTube card audio/images are extracted. Values: direct | background
|
||
"maxHeight": 720 // Maximum video height downloaded for the YouTube background media cache. Set to 0 for unlimited.
|
||
} // Media cache setting.
|
||
}, // Defaults for managed subtitle language preferences and YouTube subtitle loading.
|
||
|
||
// ==========================================
|
||
// Anilist
|
||
// Anilist API credentials and update behavior.
|
||
// Includes optional auto-sync for a merged MRU-based character dictionary in bundled Yomitan.
|
||
// Character dictionaries are keyed by AniList media ID (no season/franchise merge).
|
||
// ==========================================
|
||
"anilist": {
|
||
"enabled": false, // Enable AniList post-watch progress updates. Values: true | false
|
||
"accessToken": "", // Optional explicit AniList access token override; leave empty to use locally stored token from setup.
|
||
"characterDictionary": {
|
||
"maxLoaded": 3, // Maximum number of most-recently-used anime snapshots included in the merged Yomitan character dictionary.
|
||
"profileScope": "all", // Yomitan profile scope for character dictionary settings updates. Values: all | active
|
||
"collapsibleSections": {
|
||
"description": false, // Open the Description section by default in character dictionary glossary entries. Values: true | false
|
||
"characterInformation": false, // Open the Character Information section by default in character dictionary glossary entries. Values: true | false
|
||
"voicedBy": false // Open the Voiced by section by default in character dictionary glossary entries. Values: true | false
|
||
} // Collapsible sections setting.
|
||
} // Character dictionary setting.
|
||
}, // Anilist API credentials and update behavior.
|
||
|
||
// ==========================================
|
||
// Yomitan
|
||
// Optional external Yomitan profile integration.
|
||
// Setting yomitan.externalProfilePath switches SubMiner to read-only external-profile mode.
|
||
// For GameSentenceMiner on Linux, the default overlay profile is usually ~/.config/gsm_overlay.
|
||
// In external-profile mode SubMiner will not import, delete, or modify Yomitan dictionaries/settings.
|
||
// ==========================================
|
||
"yomitan": {
|
||
"externalProfilePath": "" // Optional external Yomitan Electron profile path to use in read-only mode for shared dictionaries/settings. Example: ~/.config/gsm_overlay
|
||
}, // Optional external Yomitan profile integration.
|
||
|
||
// ==========================================
|
||
// MPV Launcher
|
||
// SubMiner-managed mpv launch and bundled plugin options.
|
||
// Set mpv.socketPath to the IPC socket used by the launcher, Electron app, and bundled plugin.
|
||
// autoStartSubMiner starts SubMiner in the background; auto_start_overlay only controls visible overlay display.
|
||
// Set mpv.launchMode to choose normal, maximized, or fullscreen SubMiner-managed mpv playback.
|
||
// Set mpv.profile to pass an mpv profile to managed mpv launches; leave it blank to pass none.
|
||
// Leave mpv.executablePath blank to auto-discover mpv from SUBMINER_MPV_PATH, PATH, or (macOS) Homebrew and /Applications/mpv.app.
|
||
// ==========================================
|
||
"mpv": {
|
||
"executablePath": "", // Optional absolute path to the mpv binary SubMiner starts itself (Windows launches, Jellyfin casting, timing preview). Leave empty to auto-discover from SUBMINER_MPV_PATH, PATH, and on macOS the Homebrew and /Applications/mpv.app locations.
|
||
"launchMode": "normal", // Default window state for SubMiner-managed mpv launches. Values: normal | maximized | fullscreen
|
||
"profile": "", // Optional mpv profile name passed to SubMiner-managed mpv launches. Leave empty to pass no profile.
|
||
"socketPath": "/tmp/subminer-socket", // mpv IPC socket path used by SubMiner-managed playback and the bundled mpv plugin.
|
||
"backend": "auto", // Window tracking backend passed to the bundled mpv plugin. Auto detects the current platform. Values: auto | hyprland | sway | x11 | macos | windows
|
||
"autoStartSubMiner": true, // Start SubMiner in the background when SubMiner-managed mpv loads a file. Values: true | false
|
||
"pauseUntilOverlayReady": true, // Pause mpv on visible-overlay auto-start until SubMiner signals subtitle tokenization readiness. Values: true | false
|
||
"subminerBinaryPath": "", // Optional SubMiner app binary path passed to the bundled mpv plugin. Leave empty to use the launcher-detected app path.
|
||
"aniskipEnabled": true, // Enable AniSkip intro detection, chapter markers, and the skip-intro key. Values: true | false
|
||
"aniskipButtonKey": "TAB" // mpv key used to skip the detected intro while the skip prompt is visible.
|
||
}, // SubMiner-managed mpv launch and bundled plugin options.
|
||
|
||
// ==========================================
|
||
// Jellyfin
|
||
// Optional Jellyfin integration for auth, browsing, and playback launch.
|
||
// Access token is stored in local encrypted token storage after login/setup.
|
||
// jellyfin.accessToken remains an optional explicit override in config.
|
||
// ==========================================
|
||
"jellyfin": {
|
||
"enabled": false, // Enable optional Jellyfin integration and CLI control commands. Values: true | false
|
||
"serverUrl": "", // Base Jellyfin server URL (for example: http://localhost:8096).
|
||
"recentServers": [], // Recently authenticated Jellyfin server URLs shown in setup.
|
||
"username": "", // Default Jellyfin username used during CLI login.
|
||
"defaultLibraryId": "", // Optional default Jellyfin library ID for item listing.
|
||
"remoteControlEnabled": true, // Enable Jellyfin remote cast control mode. Values: true | false
|
||
"remoteControlAutoConnect": true, // Auto-connect to the configured remote control target. Values: true | false
|
||
"autoAnnounce": false, // When enabled, automatically trigger remote announce/visibility check on websocket connect. Values: true | false
|
||
"pullPictures": false, // Enable Jellyfin poster/icon fetching for launcher menus. Values: true | false
|
||
"iconCacheDir": "/tmp/subminer-jellyfin-icons", // Directory used by launcher for cached Jellyfin poster icons.
|
||
"directPlayPreferred": true, // Try direct play before server-managed transcoding when possible. Values: true | false
|
||
"directPlayContainers": [
|
||
"mkv",
|
||
"mp4",
|
||
"webm",
|
||
"mov",
|
||
"flac",
|
||
"mp3",
|
||
"aac"
|
||
], // Container allowlist for direct play decisions.
|
||
"transcodeVideoCodec": "h264" // Preferred transcode video codec when direct play is unavailable.
|
||
}, // Optional Jellyfin integration for auth, browsing, and playback launch.
|
||
|
||
// ==========================================
|
||
// Discord Rich Presence
|
||
// Optional Discord Rich Presence activity card updates for current playback/study session.
|
||
// Uses official SubMiner Discord app assets for polished card visuals.
|
||
// ==========================================
|
||
"discordPresence": {
|
||
"enabled": true, // Enable optional Discord Rich Presence updates. Values: true | false
|
||
"presenceStyle": "default", // Presence card text preset: "default" (clean bilingual), "meme" (Mining and crafting), "japanese" (fully JP), or "minimal". Values: default | meme | japanese | minimal
|
||
"updateIntervalMs": 3000, // Minimum interval between presence payload updates.
|
||
"debounceMs": 750 // Debounce delay used to collapse bursty presence updates.
|
||
}, // Optional Discord Rich Presence activity card updates for current playback/study session.
|
||
|
||
// ==========================================
|
||
// Immersion Tracking
|
||
// Enable/disable immersion tracking.
|
||
// Set dbPath to override the default sqlite database location.
|
||
// Policy tuning is available for queue, flush, and retention values.
|
||
// ==========================================
|
||
"immersionTracking": {
|
||
"enabled": true, // Enable immersion tracking for mined subtitle metadata. Values: true | false
|
||
"dbPath": "", // Optional SQLite database path for immersion tracking. Empty value uses the default app data path.
|
||
"batchSize": 25, // Buffered telemetry/event writes per SQLite transaction.
|
||
"flushIntervalMs": 500, // Max delay before queue flush in milliseconds.
|
||
"queueCap": 1000, // In-memory write queue cap before overflow policy applies.
|
||
"payloadCapBytes": 256, // Max JSON payload size per event before truncation.
|
||
"maintenanceIntervalMs": 86400000, // Maintenance cadence (prune + rollup + vacuum checks).
|
||
"retentionMode": "preset", // Retention mode (`preset` uses preset values, `advanced` uses explicit values). Values: preset | advanced
|
||
"retentionPreset": "balanced", // Retention preset when `retentionMode` is `preset`. Values: minimal | balanced | deep-history
|
||
"retention": {
|
||
"eventsDays": 0, // Raw event retention window in days. Use 0 to keep all.
|
||
"telemetryDays": 0, // Telemetry retention window in days. Use 0 to keep all.
|
||
"sessionsDays": 0, // Session retention window in days. Use 0 to keep all.
|
||
"dailyRollupsDays": 0, // Daily rollup retention window in days. Use 0 to keep all.
|
||
"monthlyRollupsDays": 0, // Monthly rollup retention window in days. Use 0 to keep all.
|
||
"vacuumIntervalDays": 0 // Minimum days between VACUUM runs. Use 0 to disable.
|
||
}, // Retention setting.
|
||
"lifetimeSummaries": {
|
||
"global": true, // Maintain global lifetime stats rows. Values: true | false
|
||
"anime": true, // Maintain per-anime lifetime stats rows. Values: true | false
|
||
"media": true // Maintain per-media lifetime stats rows. Values: true | false
|
||
} // Lifetime summaries setting.
|
||
}, // Enable/disable immersion tracking.
|
||
|
||
// ==========================================
|
||
// Stats Dashboard
|
||
// Local immersion stats dashboard served on localhost and available as an in-app overlay.
|
||
// Uses the immersion tracking database for overview, trends, sessions, and vocabulary views.
|
||
// ==========================================
|
||
"stats": {
|
||
"toggleKey": "Backquote", // Key code to toggle the stats overlay.
|
||
"markWatchedKey": "KeyW", // Key code to mark the current video as watched and advance to the next playlist entry.
|
||
"serverPort": 6969, // Port for the stats HTTP server.
|
||
"autoStartServer": true, // Automatically start the stats server on launch. Values: true | false
|
||
"autoOpenBrowser": false // Automatically open the stats dashboard in a browser when the server starts. Values: true | false
|
||
} // Local immersion stats dashboard served on localhost and available as an in-app overlay.
|
||
}
|