* fix(jellyfin): show overlay, inject plugin, and fix stats title on playb - Show visible overlay automatically during Jellyfin playback so subtitleStyle applies - Inject bundled mpv plugin on auto-launch so keybindings work without overlay focus - Group Jellyfin playback stats under item metadata (jellyfin://host/item/id) instead of stream URLs so episodes merge with matching local titles - Mark ffsubsync unavailable in subsync modal for remote media paths - Drain queued second-instance commands even when onReady throws * fix(overlay): stabilize macOS focus handoff and sidebar Yomitan pause - Keep overlay visible during macOS foreground probe after overlay blur - Hold sidebar hover-pause while a Yomitan lookup popup remains open * fix(jellyfin): fix discovery loop, device identity, tray state, and Disc - Derive device identity from OS hostname; remove legacy configurable client/device fields - Prevent discovery playback from reloading active item, misreporting pause state, and duplicate overlay restores - Restart stale tray discovery sessions without re-login when server drops SubMiner cast target - Sync tray discovery checkbox state on Linux after CLI/startup/remote-session changes - Stop Discord presence falling back to stream URLs; prime title before tokenized stream loads - Fix picker library discovery when log level is above info - Fix config.example.jsonc trailing commas and array formatting * docs(release): trim and consolidate prerelease notes for 0.15.0 - Remove breaking changes section and several redundant bullet points - Consolidate per-platform updater notes into a single entry - Normalize em-dash separators to hyphens in section headers * fix(config): remove trailing commas from config.example.jsonc - Strip trailing commas throughout both config.example.jsonc copies - Reformat inline arrays to multi-line for JSON strictness - Update Jellyfin subtitle preload and playback launch tests and impl * fix(tokenizer): preserve known-word highlight when POS filters suppress - Known-word cache matches now set isKnown=true even for tokens excluded by POS filters - POS exclusion gate suppresses N+1, frequency, and JLPT only; known status is computed before the gate - Jellyfin subtitle preload continues after cleanup failures instead of aborting - Update config docs and option description to document the known-word bypass behavior * fix(jellyfin): send explicit hide/show overlay instead of toggle - Track overlay visibility in plugin state; y-t uses explicit hide/show commands when state is known - Prevent paused Jellyfin playback from resuming on overlay hide - Fix subtitle cache cleanup to only remove dirs after successful cleanup * fix(jellyfin): fix remote progress sync, seek reporting, and startup sto - arm active playback before loadfile with loadedMediaPath: null to suppress premature stop events - force immediate progress report on seek-like position jumps at the mpv time-pos level - send positionTicks and failed=false in reportStopped payload - remove EventName from HTTP timeline payloads (websocket-only field) - add startup grace window to drop stop events before media finishes loading * fix(jellyfin): fix overlay toggle sync, redirect reload, and AppImage bi - Sync visible-overlay state back to plugin via script messages to avoid toggle/hide drift - Collapse duplicate toggle events within 250ms to prevent hide-then-show on single keypress - Preserve manual hide across Jellyfin path-changing redirects even when media-title drops - Rearm managed subtitle defaults on path-changing redirects - Route toggleVisibleOverlay session binding through plugin toggle instead of app-side IPC - Show Linux/Hyprland overlay passively (showInactive) to avoid stealing mpv keyboard focus - Fix AppImage binary resolution to prefer $APPIMAGE env over mounted inner binary - Add stats window layer management so delete/update dialogs appear above stats window - Fix Jellyfin remote progress sync during Linux websocket reconnect windows * Fix CodeRabbit review feedback * fix(jellyfin): subtitle timing, resume progress, and overlay sync - Add per-stream subtitle delay persistence and auto timeline-offset correction - Strip server-selected subtitle stream from mpv load URL; suppress plugin subtitle rearm and auto-start during app-managed preload - Fix resume position lost when mpv resets on stop; use last known position for final progress/stopped reports - Keep Play vs Resume distinct to avoid early seek race on normal play - Fix discovery resume when remote play sends StartPositionTicks=0 despite saved progress - Deduplicate show/hide overlay commands using recorded visibility state - Rewrite docs-site Jellyfin page around cast-to-device UX * test: update lifecycle cleanup assertion * fix: clear aborted playback state, fix overlay passthrough, and guard du - Reset app_managed_playback_pending on lifecycle cleanup to prevent state leak into next item - Record visible overlay action only after command succeeds, not before - Non-native passive overlay now always click-through on re-show (fix isNonNativePassiveOverlay ordering) - Defer activeParsedSubtitleMediaPath assignment until after prefetch completes - Move autoplay gate release into the hide branch of toggleVisibleOverlay - Clear active Jellyfin playback when stopping media that never loaded - Reset managed subtitle delay and delay key when no external tracks are available - Await async removeDir in subtitle cache cleanup - Guard duplicate delete clicks in MediaDetailView and SessionsTab with refs - Escape key in DeleteConfirmDialog now calls stopPropagation and stopImmediatePropagation
13 KiB
Mining Workflow
This guide walks through the sentence mining loop — from watching a video to creating Anki cards with audio, screenshots, and context.
Overview
Sentence mining means turning real sentences you encounter while watching native video into Anki flashcards, so you learn vocabulary in the context where you actually met it. SubMiner automates the tedious parts of that loop.
SubMiner runs as a transparent overlay on top of mpv (the video player). As subtitles play, the overlay displays them as interactive text. You hover a word, trigger a Yomitan dictionary lookup with your configured lookup key/modifier, then create an Anki card with a single action. SubMiner automatically attaches the sentence, an audio clip, and a screenshot to that card — no manual copy-pasting or screen capturing.
Yomitan is the popup dictionary that shows definitions when you hover or scan a word. AnkiConnect is the add-on that lets SubMiner talk to Anki. Both are set up during installation — see Anki Integration if you have not configured them yet.
Creating Anki Cards
There are four ways to create or enrich cards, depending on your workflow.
1. Auto-Update from Yomitan
This is the most common flow. Yomitan creates a card in Anki, and SubMiner enriches it automatically.
- Hover a word, then trigger Yomitan lookup → Yomitan popup appears.
- Click the Anki icon in Yomitan to add the word.
- SubMiner receives or detects the new card:
- Proxy mode (default,
ankiConnect.proxy.enabled: true): immediate enrich after a successfuladdNote/addNotesis pushed through the local proxy. - Polling mode (fallback, when the proxy is disabled): detects new cards via AnkiConnect polling (
ankiConnect.pollingRate, default 3 seconds).
- Proxy mode (default,
- SubMiner updates the card with:
- Sentence: The current subtitle line.
- Audio: Extracted from the video using the subtitle's start/end timing (plus optional configured padding).
- Image: A screenshot or animated clip from the current playback position.
- Translation: From the secondary subtitle track, or generated via AI if configured.
- MiscInfo: Metadata like filename and timestamp.
Configure which fields to fill in ankiConnect.fields. See Anki Integration for details.
2. Manual Update from Clipboard
If you prefer a hands-on approach (animecards-style), you can copy the current subtitle to the clipboard and then paste it onto the last-added Anki card:
- Add a word via Yomitan as usual.
- Press
Ctrl/Cmd+Cto copy the current subtitle line to the clipboard.- For multiple lines: press
Ctrl/Cmd+Shift+C, then a digit1–9to select how many recent subtitle lines to combine. The combined text is copied to the clipboard.
- For multiple lines: press
- Press
Ctrl/Cmd+Vto update the last-added card with the clipboard contents plus audio, image, and translation — the same fields auto-update would fill.
Manual clipboard updates always replace generated sentence audio, even when ankiConnect.behavior.overwriteAudio is disabled. The word audio field is left unchanged because the word itself does not change in this flow.
This is useful when auto-update is disabled or when you want explicit control over which subtitle line gets attached to the card.
| Shortcut | Action | Config key |
|---|---|---|
Ctrl/Cmd+C |
Copy current subtitle | shortcuts.copySubtitle |
Ctrl/Cmd+Shift+C + digit |
Copy multiple recent lines | shortcuts.copySubtitleMultiple |
Ctrl/Cmd+V |
Update last card from clipboard | shortcuts.updateLastCardFromClipboard |
3. Mine Sentence (Hotkey)
Create a standalone sentence card without going through Yomitan:
- Mine current sentence:
Ctrl/Cmd+S(configurable viashortcuts.mineSentence) - Mine multiple lines:
Ctrl/Cmd+Shift+Sfollowed by a digit 1–9 to select how many recent subtitle lines to combine.
The sentence card uses the note type configured in isLapis.sentenceCardModel and always maps sentence/audio to Sentence and SentenceAudio.
::: warning Requires Lapis/Kiku note type
Sentence card creation requires a Lapis or Kiku compatible note type and ankiConnect.isLapis.enabled: true in your config. See Anki Integration — Sentence Cards for setup.
:::
4. Mark as Audio Card
After adding a word via Yomitan, press the audio card shortcut to overwrite the audio with a longer clip spanning the full subtitle timing.
::: warning Requires Lapis/Kiku note type
Audio card marking requires a Lapis or Kiku compatible note type and ankiConnect.isLapis.enabled: true in your config. See Anki Integration — Sentence Cards for setup.
:::
Field Grouping (Kiku)
If you mine the same word from different sentences, SubMiner can merge the cards instead of creating duplicates. This feature is designed for use with Kiku and similar note types that support grouped fields.
- You add a word via Yomitan.
- SubMiner detects the new card and checks if a card with the same expression already exists.
- If a duplicate is found (this requires
ankiConnect.isKiku.fieldGroupingto be set to"auto"or"manual"; it defaults to"disabled"):- Auto mode (
ankiConnect.isKiku.fieldGrouping: "auto"): Merges automatically. Both sentences, audio clips, and images are combined into the existing card. The duplicate is optionally deleted. - Manual mode (
ankiConnect.isKiku.fieldGrouping: "manual"): A modal appears showing both cards side by side. You choose which card to keep and preview the merged result before confirming.
- Auto mode (
See Anki Integration — Field Grouping for configuration options, merge behavior, and modal keyboard shortcuts.
Overlay Model
SubMiner uses one overlay window with modal surfaces. It carries two subtitle bars — a primary reading bar and a secondary translation/context bar — plus modal dialogs that open on top.
Toggle the entire overlay window with Alt+Shift+O (global) or y-t (mpv plugin).
Primary Subtitle Layer
The primary bar renders subtitles as tokenized hoverable word spans. Each word is a separate element with reading and headword data attached. This plane is styled independently from mpv subtitles and supports:
- Word-level hover targets for Yomitan lookup
- Auto pause/resume on subtitle hover (enabled by default via
subtitleStyle.autoPauseVideoOnHover) - Auto pause/resume while the Yomitan popup is open (enabled by default via
subtitleStyle.autoPauseVideoOnYomitanPopup) - Right-click to pause/resume
- Right-click + drag to reposition subtitles
- Reading annotations — known words, N+1 targets, character-name matches, JLPT levels, and frequency hits can all be visually highlighted
Secondary Subtitle Bar
The secondary bar is a compact top-strip region in the same overlay window. It shows a secondary subtitle track (typically English) for translation/context while keeping the primary reading flow below. It is useful for:
- Quick comprehension checks without leaving the mining flow.
- Auto-populating the translation field on mined cards — when a card is created, SubMiner uses the secondary subtitle text as the translation field value (unless AI translation is configured to override it).
It is controlled by secondarySub configuration and shares its lifecycle with the main overlay window. Cycle which track feeds it with Shift+J.
Display Modes
Both the primary and secondary subtitle bars share the same three visibility modes, and each can be changed independently at runtime:
- Hidden — the bar is not shown.
- Visible — the bar is always shown.
- Hover — the bar is revealed only while you hover over the overlay.
By default the primary bar is visible (subtitleStyle.primaryDefaultMode) and the secondary bar is hover (secondarySub.defaultMode).
Cycle each bar's mode at runtime with its own shortcut:
| Shortcut | Action | Config key |
|---|---|---|
V |
Cycle primary subtitle mode (hidden → visible → hover) | overlay-local |
Ctrl/Cmd+Shift+V |
Cycle secondary subtitle mode (hidden → visible → hover) | shortcuts.toggleSecondarySub |
Modal Surfaces
Jimaku search, field-grouping, runtime options, and manual subsync open as modal surfaces on top of the same overlay window.
Looking Up Words
- Hover over the subtitle area — the overlay activates pointer events.
- Hover the word you want. SubMiner keeps per-token boundaries so Yomitan can target that token cleanly.
- Trigger Yomitan lookup with your configured lookup key/modifier (for example
Shiftif that is how your Yomitan profile is set up). - Yomitan opens its lookup popup for the hovered token.
- From the popup, add the word to Anki.
Controller Workflow
With a gamepad connected and keyboard-only mode enabled, the full mining loop works without a mouse or keyboard:
- Navigate — push the left stick left/right to move the token highlight across subtitle words.
- Look up — press
Ato trigger Yomitan lookup on the highlighted word. - Browse the popup — push the left stick up/down to smooth-scroll through the Yomitan popup, or use the right stick for larger jumps.
- Cycle audio — press
R1to move to the next dictionary audio entry,L1to play the current one. - Mine — press
Xto create an Anki card for the current sentence (same asCtrl+S). - Close — press
Bto dismiss the Yomitan popup and return to subtitle navigation. - Pause/resume — press
L3(left stick click) to toggle mpv pause at any time.
After controller support is enabled, the controller and keyboard can be used interchangeably — switching mid-session is seamless. Toggle keyboard-only mode on or off with Y on the controller.
See Usage — Controller Support for setup details and Configuration — Controller Support for the full mapping and tuning options.
Subtitle Sync (Subsync)
If your subtitle file is out of sync with the audio, SubMiner can resynchronize it using alass or ffsubsync.
- Open the subsync modal from the overlay.
- Select the sync engine (alass or ffsubsync).
- For alass, select a reference subtitle track from the video.
- SubMiner runs the sync and reloads the corrected subtitle.
For remote streams, including Jellyfin playback, the modal only offers alass. Jellyfin subtitle URLs are cached as temporary subtitle files so alass can read them, but the video stream is not downloaded. ffsubsync needs direct access to the local media file and is unavailable for stream URLs.
Install the sync tools separately — see Troubleshooting if the tools are not found.
Texthooker
SubMiner runs a local HTTP server at http://127.0.0.1:5174 (configurable port) that serves a texthooker UI. This allows external tools — such as a browser-based Yomitan instance — to receive subtitle text in real time.
The texthooker page displays the current subtitle and updates as new lines arrive. This is useful if you prefer to do lookups in a browser rather than through the overlay's built-in Yomitan.
If you want to build your own browser client, websocket consumer, or automation relay, see WebSocket / Texthooker API & Integration.
Related Features
These features support the mining loop but have their own dedicated pages:
- Jimaku subtitle search — search and download anime subtitle files directly from the overlay (
Ctrl+Shift+Jby default), then load them into mpv. - N+1 word highlighting — cross-reference your Anki decks to highlight known words, making true N+1 sentences (exactly one unknown word) easy to spot during immersion.
- Immersion tracking — log watching and mining activity to a local database and view session times, words seen, and cards mined in the built-in stats dashboard.
Next: Anki Integration — field mapping, media generation, and card enrichment configuration.