Files
SubMiner/docs-site/troubleshooting.md
T
sudacode b1bdeabca8 fix(jellyfin): show overlay, inject plugin, and fix stats title on playback (#77)
* 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
2026-05-24 18:40:56 -07:00

17 KiB

Troubleshooting

Common issues and how to resolve them. Most problems fall into one of a few buckets — the overlay shows but subtitles don't (see MPV Connection), cards aren't being created or come out empty (see AnkiConnect), or word lookups don't appear (see Yomitan). If an error message popped up on screen, search this page for the exact text — most headings below are quoted error strings.

MPV Connection

Overlay starts but shows no subtitles

SubMiner connects to mpv via a Unix socket (or named pipe on Windows). If the socket does not exist or the path does not match, the overlay will appear but subtitles will never arrive.

  • Ensure mpv is running with --input-ipc-server=/tmp/subminer-socket.
  • If you use a custom socket path, set it in both your mpv config and SubMiner config (mpv.socketPath).
  • The subminer wrapper script sets the socket automatically when it launches mpv. If you launch mpv yourself, the --input-ipc-server flag is required.

SubMiner retries the connection automatically with increasing delays (200 ms, 500 ms, 1 s, 2 s on first connect; 1 s, 2 s, 5 s, 10 s on reconnect). If mpv exits and restarts, the overlay reconnects without needing a restart.

Logging and App Mode

  • Default log output is info.
  • Use --log-level for more/less output.
  • Use --dev/--debug only to force app/dev mode (for example to get dev behavior from the overlay/app); they do not change log verbosity.
  • You can combine both, for example SubMiner.AppImage --start --dev --log-level debug, when you need maximum diagnostics.

Performance and Resource Impact

At a glance

  • Baseline: SubMiner --start is usually lightweight for normal playback.
  • Common spikes come from:
    • first subtitle parse/tokenization bursts
    • media generation (ffmpeg audio/image and AVIF paths)
    • media sync and subtitle tooling (alass, ffsubsync)
    • ankiConnect enrichment (plus polling overhead when proxy mode is disabled)

If playback feels sluggish

  1. Reduce overlay workload:
  • set secondary subtitles hidden:
    • secondarySub.defaultMode: "hidden"
  • disable optional enrichment:
    • subtitleStyle.enableJlpt: false
    • subtitleStyle.frequencyDictionary.enabled: false
  1. Reduce rendering pressure:
  • lower subtitleStyle.fontSize
  • keep overlay complexity minimal during heavy CPU periods
  1. Reduce media overhead:
  • keep ankiConnect.media.imageType set to static (avoid animated AVIF unless needed)
  • lower ankiConnect.media.imageQuality
  • reduce ankiConnect.media.maxMediaDuration
  1. Lower integration cost:
  • disable AI translation when not needed (ankiConnect.ai.enabled: false)
  • if needed, run immersion telemetry with lower duration expectations (immersionTracking.enabled: false for constrained sessions)
  • favor the default lightweight YouTube subtitle startup settings on low-resource systems

Practical low-impact profile

{
  "subtitleStyle": {
    "fontSize": 30,
    "enableJlpt": false,
    "frequencyDictionary": {
      "enabled": false
    }
  },
  "secondarySub": {
    "defaultMode": "hidden"
  },
  "ankiConnect": {
    "media": {
      "imageType": "static",
      "imageQuality": 80,
      "maxMediaDuration": 12
    },
    "ai": {
      "enabled": false
    }
  },
  "immersionTracking": {
    "enabled": false
  }
}

If usage is still high

  • Confirm only one SubMiner instance is running.
  • Check whether bottlenecks are ffmpeg, yt-dlp, or sync tooling in system monitor.
  • Use info logs by default; keep debug for targeted diagnosis.
  • Reproduce once with SubMiner.AppImage --start --log-level debug and open DevTools (y then d) if freezes recur.

"Failed to parse MPV message"

Logged when a malformed JSON line arrives from the mpv socket. Usually harmless — SubMiner skips the bad line and continues. If it happens constantly, check that nothing else is writing to the same socket path.

Updates

"Update check failed"

Manual update checks show this when GitHub Releases or updater metadata cannot be reached. Check your network connection, then try again from the tray menu or:

subminer -u

Automatic checks log failures quietly so playback is not interrupted.

"SubMiner is up to date" but a prerelease exists

SubMiner uses the configured release channel for update checks. Set updates.channel to "prerelease" in config.jsonc when you want update checks to include beta and RC releases.

Launcher update shows a sudo command

The detected launcher is installed in a protected path such as /usr/local/bin/subminer or /usr/bin/subminer. SubMiner does not elevate itself. Run the command shown in the popup to replace the launcher after checksum verification.

OSD update notification did not appear

updates.notificationType: "osd" uses the existing mpv/overlay notification path. If mpv is disconnected, SubMiner logs the update and does not force-start the overlay. Use "system" or "both" if you want OS notifications outside playback.

AnkiConnect

"AnkiConnect: unable to connect"

First confirm you've completed the Anki Integration prerequisites — Anki must be running with the AnkiConnect add-on installed.

SubMiner connects to the active Anki endpoint:

  • ankiConnect.url (direct mode, default http://127.0.0.1:8765)
  • http://<ankiConnect.proxy.host>:<ankiConnect.proxy.port> (proxy mode)

This error means the active endpoint is unavailable, or (in proxy mode) the proxy cannot reach ankiConnect.proxy.upstreamUrl.

  • If you changed the AnkiConnect port, update ankiConnect.url (or ankiConnect.proxy.upstreamUrl if using proxy mode).
  • If using external Yomitan/browser clients, confirm they point to your SubMiner proxy URL.

SubMiner retries with exponential backoff (up to 5 s) and suppresses repeated error logs after 5 consecutive failures. When Anki comes back, you will see "AnkiConnect connection restored".

Cards are created but fields are empty

Field names in your config must match your Anki note type exactly (case-sensitive). Check ankiConnect.fields — for example, if your note type uses SentenceAudio but your config says Audio, the field will not be populated.

See Anki Integration for the full field mapping reference.

"Update failed" OSD message

Shown when SubMiner tries to update a card that no longer exists, or when AnkiConnect rejects the update. Common causes:

  • The card was deleted in Anki between creation and enrichment update.
  • The note type changed and a mapped field no longer exists.

Overlay

Overlay does not appear

  • Confirm SubMiner is running: SubMiner.AppImage --start or check for the process.
  • On Linux, the overlay requires a supported window backend. Hyprland and Sway have native Wayland support; all other compositors require both mpv and SubMiner to run under X11 or Xwayland (xdotool and xwininfo must be installed).
  • On macOS, grant Accessibility permission to SubMiner in System Settings > Privacy & Security > Accessibility.

Overlay appears but clicks pass through / cannot interact

  • Make sure you are hovering over subtitle text — the overlay only becomes interactive when the cursor is over a subtitle.
  • On macOS/Windows: toggle the overlay off and back on (Alt+Shift+O) to re-enable pointer events.
  • On Linux: mouse event handling is unreliable in some Electron/compositor combinations. If clicks consistently fail, toggle the overlay off, click the underlying mpv window, then toggle it back on.

Overlay briefly freezes after a modal/runtime error

  • Renderer errors now trigger an automatic recovery path. You should see a short toast ("Renderer error recovered. Overlay is still running.").
  • Recovery closes any open modal and restores click-through/shortcuts automatically without interrupting mpv playback.
  • If errors keep recurring, toggle the overlay's DevTools using overlay chord y then d (or global F12) and inspect the renderer overlay recovery error payload for stack trace + modal/subtitle context.

Overlay is on the wrong monitor or position

SubMiner positions the overlay by tracking the mpv window. If tracking fails:

  • Hyprland: Ensure hyprctl is available.
  • Sway: Ensure swaymsg is available.
  • X11: Ensure xdotool and xwininfo are installed.

If the overlay position is slightly off, right-click and drag on subtitle text to fine-tune the overlay subtitle offset.

Yomitan

If you haven't set up dictionaries yet, see Yomitan setup first.

"Yomitan extension not found in any search path"

SubMiner bundles Yomitan and searches for it in these locations (in order):

  1. build/yomitan (local/source build output)
  2. <resources>/yomitan (Electron resources path)
  3. /usr/share/SubMiner/yomitan
  4. ~/.config/SubMiner/yomitan (user-data fallback on Linux)

SubMiner does not load the source tree directly from vendor/subminer-yomitan; source builds must produce build/yomitan first.

If you installed from the AppImage and see this error, the package may be incomplete. Re-download the AppImage or place the unpacked Yomitan extension manually in ~/.config/SubMiner/yomitan.

Yomitan lookup popup does not appear when hovering words or triggering lookup

  • Verify Yomitan loaded successfully — check the terminal output for "Loaded Yomitan extension".
  • Yomitan requires dictionaries to be installed. Open Yomitan settings (Alt+Shift+Y or SubMiner.AppImage --yomitan) and confirm at least one dictionary is imported.
  • If yomitan.externalProfilePath is set, import/check dictionaries in the external app/profile instead. SubMiner treats that profile as read-only and does not open its own Yomitan settings window.
  • If the overlay shows subtitles but hover lookup never resolves on tokens, the tokenizer may have failed. See the MeCab section below.

MeCab / Tokenization

"MeCab not found on system"

This is informational, not an error. SubMiner tokenization is driven by Yomitan's internal parser. MeCab availability checks may still run for auxiliary token metadata, but MeCab is not used as a tokenization fallback path.

To install MeCab:

  • Arch Linux: sudo pacman -S mecab mecab-ipadic
  • Ubuntu/Debian: sudo apt install mecab libmecab-dev mecab-ipadic-utf8
  • macOS: brew install mecab mecab-ipadic

Words are not segmented correctly

Japanese word boundaries depend on Yomitan parser output. If segmentation seems wrong:

  • Verify Yomitan dictionaries are installed and active.
  • Note that CJK characters without spaces are segmented using parser heuristics, which is not always perfect.

Media Generation

"FFmpeg not found"

SubMiner uses FFmpeg to extract audio clips and generate screenshots. Install it:

  • Arch Linux: sudo pacman -S ffmpeg
  • Ubuntu/Debian: sudo apt install ffmpeg
  • macOS: brew install ffmpeg

Without FFmpeg, card creation still works but audio and image fields will be empty.

Audio or screenshot generation hangs

Media generation has a 30-second timeout (60 seconds for animated AVIF). If your video file is on a slow network mount or the codec requires software decoding, generation may time out. Try:

  • Using a local copy of the video file.
  • Reducing media.imageQuality or switching from avif to static image type.
  • Checking that media.maxMediaDuration is not set too high.

Shortcuts

"Failed to register global shortcut"

Global shortcuts (Alt+Shift+O, Alt+Shift+Y) may conflict with other applications or desktop environment keybindings.

  • Check your DE/WM keybinding settings for conflicts.
  • Change the shortcut in your config under shortcuts.toggleVisibleOverlayGlobal.
  • On Wayland, global shortcut registration has limitations depending on the compositor. Only Hyprland and Sway are supported natively — see the Hyprland section below for shortcut passthrough rules. Other Wayland compositors require X11/Xwayland.

Overlay keybindings not working

Overlay-local shortcuts (Space, arrow keys, etc.) only work when the overlay window has focus. Click on the overlay or use the global shortcut to toggle it to give it focus.

Subtitle Timing

"Subtitle timing not found; copy again while playing"

This OSD message appears when you try to mine a sentence but SubMiner has no timing data for the current subtitle. Causes:

  • The video is paused and no subtitle has been received yet.
  • The subtitle track changed and timing data was cleared.
  • You are using an external subtitle file that mpv has not fully loaded.

Resume playback and wait for the next subtitle to appear, then try mining again.

Subtitle Sync (Subsync)

Both alass and ffsubsync are optional external dependencies. Subtitle syncing requires at least one of them to be installed.

"Configured alass executable not found"

Install alass or configure the path:

  • Arch Linux (AUR): paru -S alass
  • Cargo: cargo install alass-cli
  • Set the path: subsync.alass_path in your config.

"Configured ffsubsync executable not found"

Install ffsubsync or configure the path:

  • Arch Linux (AUR): paru -S python-ffsubsync
  • pip: pip install ffsubsync
  • Must be on PATH or configured via subsync.ffsubsync_path in your config.

"Subtitle synchronization failed"

If subtitle sync fails:

  • Ensure the reference subtitle track exists in the video (alass requires a source track).
  • Check that ffmpeg is available (used to extract the internal subtitle track).
  • Try running the sync tool manually to see detailed error output.
  • ffsubsync requires local files and cannot handle remote media streams (e.g., streaming URLs).

Jimaku

"Jimaku request failed" or HTTP 429

The Jimaku API has rate limits. If you see 429 errors, wait for the retry duration shown in the OSD message and try again. If you have a Jimaku API key, set it in jimaku.apiKey or jimaku.apiKeyCommand to get higher rate limits.

Platform-Specific

Linux

  • Wayland (Hyprland/Sway only): Native Wayland support is limited to Hyprland and Sway. Window tracking uses compositor-specific commands (hyprctl / swaymsg). If these are not on PATH, tracking will fail silently. Other Wayland compositors are not supported — both mpv and SubMiner must run under X11 or Xwayland instead.
  • X11 / Xwayland: Requires xdotool and xwininfo. If missing, the overlay cannot track the mpv window position. This is the required backend for any Wayland compositor other than Hyprland or Sway — both mpv and SubMiner must be running under X11/Xwayland for window tracking to work.
  • Tray icon missing: SubMiner creates an Electron tray icon in --background mode, but Linux trays require a StatusNotifier/AppIndicator host. Hyprland does not provide one by itself; enable a tray in Waybar, Hyprpanel, or another panel. If Electron cannot register the tray, SubMiner logs a warning that mentions the missing tray host.
  • Mouse passthrough: On Linux, Electron's mouse passthrough is unreliable. SubMiner keeps pointer events enabled, meaning you may need to toggle the overlay off to interact with mpv controls underneath.

Hyprland

SubMiner's overlay is a transparent, frameless, always-on-top Electron window. Hyprland needs window rules to keep it transparent and borderless, and pass bindings to forward global shortcuts to SubMiner.

Overlay is not transparent or has a visible border

Add these window rules to your hyprland.conf:

windowrule = float on, match:class SubMiner
windowrule = border_size 0, match:class SubMiner
windowrule = xray off override, match:class SubMiner
windowrule = no_shadow on, match:class SubMiner
windowrule = no_blur on, match:class SubMiner

Without xray off override, the compositor may render the transparent overlay incorrectly — you might see a solid background or visual artifacts instead of the mpv video underneath.

Global shortcuts not working

On Hyprland, Electron cannot register global shortcuts on its own. You must explicitly pass keybindings to SubMiner using pass rules:

bind = ALT SHIFT, O, pass, class:^(SubMiner)$
bind = ALT SHIFT, Y, pass, class:^(SubMiner)$

Add a pass rule for each global shortcut you configure. The defaults are Alt+Shift+O (toggle overlay) and Alt+Shift+Y (Yomitan settings). If you remap shortcuts.toggleVisibleOverlayGlobal to a different key, update the pass rule to match.

Without these rules, Hyprland intercepts the keypresses before they reach SubMiner, and the shortcuts silently do nothing.

Overlay stays behind mpv after fullscreen

SubMiner watches mpv's fullscreen property and refreshes the overlay geometry when it changes. If the overlay still does not move or rise above fullscreen mpv, confirm that the mpv IPC socket is connected and that hyprctl -j clients and hyprctl -j monitors work from the same environment that launched SubMiner.

For more details, see the Hyprland docs on global keybinds and window rules.

macOS

  • Accessibility permission: Required for window tracking. Grant it in System Settings > Privacy & Security > Accessibility.
  • Gatekeeper: If macOS blocks SubMiner, right-click the app and select "Open" to bypass the warning, or remove the quarantine attribute: xattr -d com.apple.quarantine /path/to/SubMiner.app