* feat(controller): add hold + press combos to main bindings Main Alt+C actions can now be learned as combos such as L1 + D-pad right. A combo fires on each press while its hold button is down, and claims its press input so token move and popup scroll ignore it until it is released. A plain action on a hold button fires on release, unless another bound button was pressed during the hold. The save path needed two changes for combos to persist. The IPC validator rebuilt bindings field by field and dropped `hold`, so Alt+C showed a combo from its local copy until the next reload turned it back into a plain button. Validator and config resolver now share one parser. Saves also replace the controller section, since the deep merge in patchRawConfig kept the old `hold` when a combo was rebound to one button. Also fixes Learn on the (D-pad) rows, which threw after cancel() cleared the capture target. * test(launcher): wait for content in background child test The test polled for the fake app's output files to exist, but the shell creates a redirect target before writing to it. A poll landing in that gap read an empty env file and failed with '' !== '1', as seen once in CI. Wait until both files have content instead. * fix(controller): keep a diagonal push from learning as a combo Learn took the first axis of a diagonal stick push as the hold and the second as the press, saving a combo that one axis could never trigger. This reached main Alt+C rows when they moved to combo capture. Axes crossing the threshold in the same poll as the first input now count as one movement. A second axis moved in a later poll still records a combo. * fix(controller): only treat simultaneous axes as one movement The diagonal push guard also blocked an axis activated in the same poll as a button, so L1 plus a stick direction could not record the stick until it was released and moved again. Apply the guard only when the first input is an axis, so that input pair records as a combo again.
SubMiner
Look up words with Yomitan or Hachidori, mine them to Anki, and track your immersion without leaving mpv
Features
Dictionary Lookups
Hover over any word in the subtitles to open the full Yomitan popup with definitions, pitch accent, and frequency data. SubMiner bundles its own Yomitan, separate from any browser install.
Yomitan remains the default. Select the bundled Hachidori backend with dictionaryBackend: "hachidori" and restart SubMiner. The tray opens the selected backend's settings. See dictionary setup for importing dictionaries, linking an external Hachidori host, and configuring Anki.
Instant Anki Mining
Create an Anki card from the exact playback moment with one key press, click, or controller input. SubMiner fills in the sentence, an audio clip, and a screenshot or animated image.
Reading Annotations
Subtitles are annotated as they play with frequency highlighting, JLPT tags, N+1 targeting, and character names from a generated dictionary. Particles and grammar-only tokens stay plain so the words worth learning stand out.
Immersion Dashboard
A stats dashboard tracks watch time, vocabulary growth, mining throughput, session history, and trends. Everything stays on your machine, with no third-party tracking.
Integrations
| YouTube | Play YouTube URLs with subtitle tracks picked by your language priorities, or choose tracks yourself in the overlay picker (Ctrl+Alt+C). Requires yt-dlp |
| AniList | Automatic episode tracking and progress sync |
| Jellyfin | Browse your Jellyfin library, or cast to SubMiner from any Jellyfin client. Setup and discovery live in the tray menu |
| Jimaku | Search and download Japanese subtitles. Requires a free Jimaku API key |
| TsukiHime | Search and download subtitles extracted from anime releases, with Japanese and secondary-language tabs (Ctrl+Shift+T). Requires xz on your PATH |
| Subtitle generation | Transcribe a video's audio into Japanese subtitles locally from the generation modal (Ctrl+Shift+G), the subtitle sidebar, or the launcher. SubMiner can download models for you; optional Silero speech detection helps focus on dialogue. Requires whisper.cpp and FFmpeg. Setup guide |
| AniSkip | Automatic intro detection with chapter markers and a one-key skip (TAB by default) |
| alass / ffsubsync | Retime a subtitle against the audio or another subtitle track (Ctrl+Alt+S). Requires alass or ffsubsync; set subsync.alass_path or subsync.ffsubsync_path if they are not in /usr/bin |
| WebSocket | Plain subtitle feed plus a dedicated annotated feed for texthooker pages and custom tools |
| Plugins | Load your own JavaScript at startup to react to playback, run timers, add key-bound actions, and show results in an overlay panel. The bundled example explains the current line with Codex. Plugin guide |
Requirements
SubMiner runs on Linux, macOS 11+, and Windows 10+. Only mpv is required to run it (plus fuse2 for the Linux AppImage). Mining cards also needs Anki with the AnkiConnect add-on. Everything else is optional.
| Dependency | Status | What it does |
|---|---|---|
| mpv | Required | The video player SubMiner draws over |
| fuse2 | Required (Linux) | Running the AppImage |
| Anki + AnkiConnect | Required to mine | Card creation from the Yomitan popup |
| ffmpeg | Recommended | Audio clips and screenshots on cards |
| MeCab + mecab-ipadic | Recommended | More accurate N+1, JLPT, and frequency highlighting |
| xdotool + xwininfo | Required (X11) | Window tracking on desktops other than Hyprland or Sway |
| yt-dlp | Optional | YouTube playback |
| xz | Optional | TsukiHime subtitle downloads (most Linux distros already have it) |
| alass / ffsubsync | Optional | Subtitle sync |
| whisper.cpp | Optional | Subtitle generation |
| guessit | Optional | Better title, season, and episode detection for AniSkip and AniList |
| fzf / rofi | Optional | Video picker in the subminer launcher (rofi is Linux only) |
| chafa, ffmpegthumbnailer | Optional | Thumbnail previews in the launcher pickers |
Platform-specific install commands
Arch Linux:
sudo pacman -S --needed mpv ffmpeg
paru -S --needed mecab-git mecab-ipadic # MeCab is only in the AUR
On desktops other than Hyprland or Sway, also install xdotool and xorg-xwininfo.
macOS:
brew install mpv ffmpeg mecab mecab-ipadic
Windows:
winget install shinchiro.mpv
winget install Gyan.FFmpeg
Then reopen your terminal and check mpv --version and ffmpeg -version. ffmpeg must be on PATH; mpv does not have to be. If mpv is not found, either add its folder (usually %LOCALAPPDATA%\Programs\mpv) to PATH or enter the full path to mpv.exe during first-run setup.
Scoop is the alternative if you want one package manager for everything. It is the only one that also carries xz:
scoop bucket add extras
scoop install extras/mpv main/ffmpeg main/yt-dlp main/xz
See the installation guide for Ubuntu, Debian, and Fedora commands and the full optional package lists.
Quick Start
1. Install SubMiner
Arch Linux (AUR)
paru -S subminer-bin
Includes the AppImage and the subminer command.
Linux (AppImage)
mkdir -p ~/.local/bin
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/SubMiner.AppImage -O ~/.local/bin/SubMiner.AppImage \
&& chmod +x ~/.local/bin/SubMiner.AppImage
The AppImage is all you need. First-run setup can install the optional subminer command, which runs on a copy of Bun bundled with the app, so you do not need Bun installed.
macOS (DMG)
Download the latest DMG from GitHub Releases and drag SubMiner.app into /Applications.
Then enable SubMiner under System Settings > Privacy & Security > Accessibility (named Device Control and Data Access on macOS 27) so the overlay can track the mpv window. Without it, SubMiner falls back to a basic window lookup that cannot tell when mpv is minimized. If macOS blocks the first launch, right-click the app and choose Open.
Windows
Download and run the latest installer (SubMiner-<version>.exe) from GitHub Releases. A portable .zip is also available.
From source
See the build-from-source guide.
2. Launch & Set Up
Start SubMiner and the setup window opens on first launch. It creates your config file, imports Yomitan dictionaries (you need at least one for lookups), and can install the subminer command. On Windows it also creates a SubMiner mpv shortcut.
subminer app --setup # AUR
~/.local/bin/SubMiner.AppImage --setup # AppImage
On macOS, open SubMiner.app from /Applications. On Windows, run SubMiner from the Start menu. To reopen setup later, run subminer app --setup.
For card creation, keep Anki open with AnkiConnect installed. SubMiner connects to it at its default address with no extra setup.
3. Mine
subminer video.mkv # play a video with SubMiner
subminer /path/to/dir # pick a file with fzf
subminer -R /path/to/dir # pick a file with rofi (Linux only)
subminer -H # watch history: replay, next, or previous episode
subminer doctor # check your setup
On Windows, double-click the SubMiner mpv shortcut or drag a video file onto it.
Starting mpv some other way? See Launching mpv yourself for the IPC socket option the overlay needs.
Documentation
Full guides on configuration, Anki setup, Jellyfin, immersion tracking, and more: docs.subminer.moe
Acknowledgments
SubMiner builds on the work of these open-source projects:
| Project | Role |
|---|---|
| ani-skip | AniSkip API client for anime intro/outro skip timestamps |
| Anacreon-Script | Inspiration for the mining workflow |
| asbplayer | Inspiration for subtitle sidebar and logic for YouTube subtitle parsing |
| Bee's Character Dictionary | Character name recognition in subtitles |
| Bun | Bundled runtime for the subminer command-line launcher |
| GameSentenceMiner | Inspiration for Electron overlay with Yomitan integration |
| jellyfin-mpv-shim | Jellyfin integration |
| Jimaku.cc | Japanese subtitle search and downloads |
| Renji's Texthooker Page | Base for the WebSocket texthooker integration |
| Yomitan | Default dictionary engine and morphological parser |
| Hachidori | Alternative dictionary backend, powered by HoshiDicts |
| yomitan-jlpt-vocab | JLPT level tags for vocabulary |
License
SubMiner is released under the GNU General Public License v3.0.
Release packages also bundle an unmodified copy of Bun, which is MIT licensed and statically links JavaScriptCore (LGPL 2.0) and TinyCC (LGPL 2.1). Its license texts and third-party notices ship inside the app under resources/bun/licenses, and each release publishes bun-v1.3.5-source.tar.gz with the corresponding source. See Bundled Bun runtime.




