Immersion mining overlay for mpv — look up words, mine to Anki, and enrich cards with context without leaving the video.
-An all-in-one immersion mining overlay for MPV with AnkiConnect and dictionary (Yomitan) integration.
+---
-## What This Project Is For
-
-SubMiner is for Japanese learners who watch subtitled content in mpv and want a low-friction mining loop:
-
-- stay inside the video while doing lookups
-- mine to Anki quickly without manual copy/paste workflows
-- preserve card context (sentence, audio, screenshot, translation, metadata)
-- reduce tool switching between player, dictionary, and card workflow
-
-## Project Goals
-
-1. Keep immersion continuous by making lookup and mining happen over mpv subtitles.
-2. Preserve card quality with context-rich media and subtitle timing.
-3. Support real daily workflows (subtitle management, sync, known-word awareness, keyboard-first controls).
-4. Stay configurable with sensible defaults and advanced customization.
-5. Evolve quickly and safely with a TypeScript codebase and automated tests that make refactors easier to ship.
-
-## Who It's For
-
-- learners using mpv as their primary immersion player
-- users already working with Yomitan and AnkiConnect
-- miners who care about long-term card quality, not just quick word capture
-
-SubMiner is likely overkill if you only want lightweight dictionary lookup without card enrichment or integrated workflow tools.
+[](https://github.com/user-attachments/assets/9235a554-ea51-4284-b14b-7bbf3defaf58)
## Features
-- Real-time subtitle display from MPV via IPC socket
-- Yomitan integration for fast, on-screen lookups
-- Japanese text tokenization using MeCab with smart word boundary detection
-- Integrated texthooker-ui server for use with Yomitan
-- Integrated WebSocket server (if [mpv_websocket](https://github.com/kuroahna/mpv_websocket) is not found) to send lines to the texthooker
-- AnkiConnect integration for automatic card creation with media (audio/image)
-- Invisible subtitle position edit mode (`Ctrl/Cmd+Shift+P`, arrow keys to adjust, `Enter`/`Ctrl+S` save, `Esc` cancel)
-
-## Demo
-
-[](https://github.com/user-attachments/assets/9235a554-ea51-4284-b14b-7bbf3defaf58)
+- **Yomitan Integration** — Hover subtitle words to trigger dictionary lookups in the player
+- **Anki Card Enrichment** — Fills sentence, audio, screenshot, and translation on new cards automatically
+- **Dual-Layer Subtitles** — Interactive visible overlay + invisible click-through layer aligned with mpv rendering
+- **N+1 Highlighting** — Marks known vocabulary from your Anki deck so you can spot new words at a glance
+- **Texthooker & WebSocket** — Built-in texthooker page with WebSocket streaming for external tools
+- **Subtitle Download & Sync** — Search Jimaku, sync with alass or ffsubsync — all from the player
+- **Keyboard-Driven** — Mine, copy, cycle display modes, and navigate from configurable shortcuts
+- **Japanese Tokenization** — MeCab-powered word boundary detection with smart grouping
## Requirements
- `mpv` with IPC socket support
-- `mecab` and `mecab-ipadic` (recommended for Japanese tokenization)
+- `mecab` and `mecab-ipadic`
- Linux: Hyprland (`hyprctl`) or X11 (`xdotool` + `xwininfo`)
- macOS: Accessibility permission for window tracking
-Optional but recommended: `yt-dlp`, `fzf`, `rofi`, `chafa`, `ffmpegthumbnailer`.
+Optional: `yt-dlp`, `fzf`, `rofi`, `chafa`, `ffmpegthumbnailer`
## Install
### Linux (AppImage)
-Download the latest release from [GitHub Releases](https://github.com/ksyasuda/SubMiner/releases/latest):
-
```bash
wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/SubMiner-0.1.0.AppImage -O ~/.local/bin/SubMiner.AppImage
chmod +x ~/.local/bin/SubMiner.AppImage
@@ -73,49 +46,34 @@ The `subminer` wrapper uses a [Bun](https://bun.sh) shebang, so `bun` must be on
```bash
git clone --recurse-submodules https://github.com/ksyasuda/SubMiner.git
cd SubMiner
-make build
-make install
+make build && make install
```
-If you already cloned without submodules:
-
-```bash
-cd SubMiner
-git submodule update --init --recursive
-```
-
-For macOS builds, signing, and platform-specific details, see [docs/installation.md](docs/installation.md).
+For macOS builds and platform details, see the [installation docs](docs/installation.md).
## Quick Start
-1. Copy and customize [`config.example.jsonc`](config.example.jsonc) to `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc`).
-2. Start mpv with IPC enabled:
-
-```bash
-mpv --input-ipc-server=/tmp/subminer-socket video.mkv
-```
-
+1. Copy [`config.example.jsonc`](config.example.jsonc) to `~/.config/SubMiner/config.jsonc`
+2. Start mpv with IPC:
+ ```bash
+ mpv --input-ipc-server=/tmp/subminer-socket video.mkv
+ ```
3. Launch SubMiner:
+ ```bash
+ subminer video.mkv
+ ```
```bash
-subminer video.mkv
-# or
-subminer https://youtu.be/...
+subminer # pick video from cwd (fzf)
+subminer -R # rofi picker
+subminer -d ~/Videos # set source directory
+subminer -r -d ~/Anime # recursive search
+subminer -p gpu-hq video.mkv # override mpv profile
+subminer -T video.mkv # disable texthooker
+subminer https://youtu.be/... # YouTube playback
```
-## Common Commands
-
-```bash
-subminer # pick video from current dir (fzf)
-subminer -R # use rofi picker
-subminer -d ~/Videos # set source directory
-subminer -r -d ~/Anime # recursive search
-subminer video.mkv # launch with default mpv profile (subminer)
-subminer -p gpu-hq video.mkv # override mpv profile
-subminer -T video.mkv # disable texthooker
-```
-
-## MPV Plugin (Optional)
+## MPV Plugin
```bash
cp plugin/subminer.lua ~/.config/mpv/scripts/
@@ -123,46 +81,23 @@ cp plugin/subminer.conf ~/.config/mpv/script-opts/
# or: make install-plugin
```
-Requires mpv IPC: `--input-ipc-server=/tmp/subminer-socket`
-
-Default chord prefix: `y` (`y-y` menu, `y-s` start, `y-S` stop, `y-t` toggle visible layer).
-Overlay Jimaku shortcut default: `Ctrl+Shift+J` (`shortcuts.openJimaku`).
+Default chord prefix: `y` (`y-y` menu, `y-s` start, `y-S` stop, `y-t` toggle overlay).
+Jimaku shortcut: `Ctrl+Shift+J`.
## Documentation
-Detailed guides live in [`docs/`](docs/README.md):
+Full guides at [**docs/**](docs/README.md):
+[Installation](docs/installation.md) · [Usage](docs/usage.md) · [Mining Workflow](docs/mining-workflow.md) · [Configuration](docs/configuration.md) · [Anki Integration](docs/anki-integration.md) · [MPV Plugin](docs/mpv-plugin.md) · [Troubleshooting](docs/troubleshooting.md) · [Architecture](docs/architecture.md)
-- [Installation](docs/installation.md) — Platform requirements, AppImage/macOS/source installs, mpv plugin
-- [Usage](docs/usage.md) — Script vs plugin workflow, keybindings, YouTube playback
-- [Mining Workflow](docs/mining-workflow.md) — End-to-end mining guide, overlay layers, card creation
-- [Configuration](docs/configuration.md) — Full config reference and option details
-- [Anki Integration](docs/anki-integration.md) — AnkiConnect setup, field mapping, media generation
-- [MPV Plugin](docs/mpv-plugin.md) — Chord keybindings, subminer.conf options, script messages
-- [Troubleshooting](docs/troubleshooting.md) — Common issues and solutions
-- [Development](docs/development.md) — Building, testing, contributing
-- [Architecture](docs/architecture.md) — Service-oriented design, composition model, and modular renderer layout (`src/renderer/{modals,handlers,utils,...}`)
+## Acknowledgments
-### Third-Party Components
-
-This project includes the following third-party components:
-
-- **[Yomitan](https://github.com/yomidevs/yomitan)** - Pop-up dictionary
-- **[texthooker-ui](https://github.com/ksyasuda/texthooker-ui/tree/subminer)** - Texthooker Page
-- **[yomitan-jlpt-vocab](https://github.com/stephenmk/yomitan-jlpt-vocab)** - JLPT Yomitan Dictionary
-- **[Jiten Frequency Dictionary](https://jiten.moe/)** - Frequency Dictionary
-
-### Acknowledgments
-
-- **[GameSentenceMiner](https://github.com/bpwhelan/GameSentenceMiner)** — Inspiration for the subtitle overlay and Yomitan integration
-- **[Jimaku.cc](https://jimaku.cc)** — Japanese subtitle provider
-
-This project cherry-picks features from the following MPV scripts, ported to TypeScript:
-
-- **[mpvacious](https://github.com/Ajatt-Tools/mpvacious)** — Sentence mining, screenshotting, and card updating logic
-- **[Anacreon-Script (animecards)](https://github.com/friedrich-de/Anacreon-Script)** — Copy/paste to card update flow
-- **[autosubsync-mpv](https://github.com/joaquintorres/autosubsync-mpv)** — Subtitle synchronization
+- [GameSentenceMiner](https://github.com/bpwhelan/GameSentenceMiner) — Inspiration for the overlay and Yomitan integration
+- [Jimaku.cc](https://jimaku.cc) — Japanese subtitle provider
+- [mpvacious](https://github.com/Ajatt-Tools/mpvacious), [Anacreon-Script](https://github.com/friedrich-de/Anacreon-Script), [autosubsync-mpv](https://github.com/joaquintorres/autosubsync-mpv) — Mining and sync logic ported to TypeScript
+**Third-party:**
+[Yomitan](https://github.com/yomidevs/yomitan) · [texthooker-ui](https://github.com/ksyasuda/texthooker-ui/tree/subminer) · [yomitan-jlpt-vocab](https://github.com/stephenmk/yomitan-jlpt-vocab) · [Jiten Frequency Dictionary](https://jiten.moe/)
## License
-GNU General Public License v3.0. See [LICENSE](LICENSE).
+[GNU General Public License v3.0](LICENSE)
diff --git a/docs/architecture.md b/docs/architecture.md
index cdb4b39..fd158c6 100644
--- a/docs/architecture.md
+++ b/docs/architecture.md
@@ -84,53 +84,63 @@ src/renderer/
## Flow Diagram
+The main process has three layers: `main.ts` delegates to composition modules that wire together domain services. The renderer runs in a separate Electron process, connected through `preload.ts`.
+
```mermaid
flowchart TD
- classDef root fill:#c6a0f6,stroke:#24273a,color:#24273a,stroke-width:2px
- classDef comp fill:#b7bdf8,stroke:#24273a,color:#24273a,stroke-width:1.5px
- classDef svc fill:#8aadf4,stroke:#24273a,color:#24273a,stroke-width:1.5px
- classDef ext fill:#a6da95,stroke:#24273a,color:#24273a,stroke-width:1.5px
+ classDef entry fill:#c6a0f6,stroke:#363a4f,color:#24273a,stroke-width:2px
+ classDef comp fill:#b7bdf8,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef svc fill:#8aadf4,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef bridge fill:#f5a97f,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef rend fill:#8bd5ca,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef ext fill:#a6da95,stroke:#363a4f,color:#24273a,stroke-width:1.5px
- Main["src/main.ts"]:::root
+ Main["main.ts"]:::entry
- subgraph Composition["Composition Modules"]
- Startup["Startup & Lifecycle"]:::comp
- IpcCli["IPC & CLI Wiring"]:::comp
- Overlay["Overlay & Shortcuts"]:::comp
- Subsync["Subsync"]:::comp
+ subgraph Comp["Composition — src/main/"]
+ Startup["Startup & Lifecycle startup · app-lifecycle startup-lifecycle · state"]:::comp
+ Wiring["Runtime Wiring ipc-runtime · cli-runtime overlay-runtime · subsync-runtime"]:::comp
end
- subgraph Services["Domain Services"]
- OverlaySvc["Overlay Services"]:::svc
- MpvSvc["MPV Stack"]:::svc
- MiningSvc["Mining & Subtitles"]:::svc
- ShortcutIpc["Shortcuts & IPC"]:::svc
+ subgraph Svc["Services — src/core/services/"]
+ Mpv["MPV Stack transport · protocol state · properties"]:::svc
+ Overlay["Overlay manager · window visibility · bridge"]:::svc
+ Mining["Mining & Subtitles mining · field-grouping subtitle-ws · tokenizer"]:::svc
+ Integrations["Integrations jimaku · subsync texthooker · yomitan"]:::svc
end
- subgraph External["External Boundaries"]
- Config["Config & CLI"]:::ext
- Trackers["Window Trackers"]:::ext
- Integrations["Jimaku & Subsync"]:::ext
+ Bridge(["preload.ts — Electron IPC"]):::bridge
+
+ subgraph Rend["Renderer — src/renderer/"]
+ Orchestration["renderer.ts orchestration · IPC wiring"]:::rend
+ UI["subtitle-render · positioning handlers · modals"]:::rend
end
- Main --> Startup
- Main --> IpcCli
- Main --> Overlay
- Main --> Subsync
+ subgraph Ext["External Systems"]
+ mpv["mpv"]:::ext
+ Anki["AnkiConnect"]:::ext
+ Jimaku["Jimaku API"]:::ext
+ Tracker["Window Tracker"]:::ext
+ end
- Startup --> OverlaySvc
- IpcCli --> ShortcutIpc
- Overlay --> OverlaySvc
- Overlay --> MpvSvc
- Subsync --> Integrations
+ Main -->|delegates| Comp
+ Startup -->|initializes| Svc
+ Wiring -->|dispatches to| Svc
- OverlaySvc --> Trackers
- MpvSvc --> MiningSvc
- ShortcutIpc --> Config
+ Overlay <--> Bridge
+ Mining <--> Bridge
+ Bridge <--> Orchestration
+ Orchestration --> UI
- style Composition fill:#363a4f,stroke:#494d64,color:#cad3f5
- style Services fill:#363a4f,stroke:#494d64,color:#cad3f5
- style External fill:#363a4f,stroke:#494d64,color:#cad3f5
+ Mpv <-->|JSON socket| mpv
+ Mining -->|HTTP| Anki
+ Integrations -->|HTTP| Jimaku
+ Overlay --> Tracker
+
+ style Comp fill:#363a4f,stroke:#494d64,color:#cad3f5
+ style Svc fill:#363a4f,stroke:#494d64,color:#cad3f5
+ style Rend fill:#363a4f,stroke:#494d64,color:#cad3f5
+ style Ext fill:#363a4f,stroke:#494d64,color:#cad3f5
```
## Composition Pattern
@@ -154,43 +164,53 @@ The composition root (`src/main.ts`) delegates to focused modules in `src/main/`
This keeps side effects explicit and makes behavior easy to unit-test with fakes.
-## Lifecycle Model
+## Program Lifecycle
-- **Startup:**
- - `src/main/startup.ts` (`startup-service`) handles initial argv/env/backend setup and decides generate-config flow vs app lifecycle start.
- - `src/main/app-lifecycle.ts` (`app-lifecycle-service`) handles Electron single-instance + lifecycle event registration.
- - `src/main/startup-lifecycle.ts` performs ready-time initialization (config load, websocket policy, tokenizer/tracker setup, overlay auto-init decisions).
-- **Runtime:**
- - CLI/shortcut/IPC events map to service calls through `src/main/cli-runtime.ts`, `src/main/ipc-runtime.ts`, and `src/main/overlay-runtime.ts`.
- - Overlay and MPV state sync through dedicated services.
- - Runtime options and mining flows are coordinated via service boundaries.
-- **Shutdown:**
- - `app-lifecycle-service` registers cleanup hooks (`will-quit`) while teardown behavior stays delegated to focused services from `src/main/*` composition modules.
+- **Startup:** `startup.ts` parses CLI args and detects the compositor backend. If `--generate-config` is passed, it writes the template and exits. Otherwise `app-lifecycle.ts` acquires the single-instance lock and registers Electron lifecycle hooks.
+- **Initialization:** Once `app.whenReady()` fires, `startup-lifecycle.ts` loads config, resolves keybindings, creates the mpv client, initializes the MeCab tokenizer, starts the window tracker, and applies WebSocket policy — then creates the overlay window and establishes the IPC bridge.
+- **Runtime:** Event-driven. mpv property changes, IPC messages, CLI commands, and keyboard shortcuts all route through the composition layer to domain services, which update state and broadcast to the renderer.
+- **Shutdown:** Electron's `will-quit` triggers service teardown — closes the mpv socket, unregisters shortcuts, stops WebSocket and texthooker servers, destroys the window tracker, and cleans up Anki state.
```mermaid
flowchart TD
- classDef phase fill:#b7bdf8,stroke:#24273a,color:#24273a,stroke-width:1.5px
- classDef decision fill:#f5a97f,stroke:#24273a,color:#24273a,stroke-width:1.5px
- classDef runtime fill:#8aadf4,stroke:#24273a,color:#24273a,stroke-width:1.5px
- classDef shutdown fill:#a6da95,stroke:#24273a,color:#24273a,stroke-width:1.5px
+ classDef start fill:#c6a0f6,stroke:#363a4f,color:#24273a,stroke-width:2px
+ classDef phase fill:#b7bdf8,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef decision fill:#f5a97f,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef init fill:#8aadf4,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef runtime fill:#8bd5ca,stroke:#363a4f,color:#24273a,stroke-width:1.5px
+ classDef shutdown fill:#ed8796,stroke:#363a4f,color:#24273a,stroke-width:1.5px
- Args["CLI args / env"]:::phase --> Startup["src/main/startup.ts"]:::phase
+ CLI["CLI args & environment"]:::start
+ CLI --> Parse["startup.ts Parse argv · detect backend · resolve config"]:::phase
+ Parse --> GenCheck{"--generate-config?"}:::decision
+ GenCheck -->|yes| GenExit["Write config template & exit"]:::phase
+ GenCheck -->|no| Lifecycle["app-lifecycle.ts Acquire single-instance lock Register Electron lifecycle hooks"]:::phase
+ Lifecycle -->|"app.whenReady()"| Ready["startup-lifecycle.ts"]:::phase
- Startup --> Decision{"generate-config?"}:::decision
+ Ready --> Init
+ subgraph Init["Initialization"]
+ direction LR
+ Config["Load config resolve keybindings"]:::init
+ Runtime["Create mpv client init MeCab tokenizer"]:::init
+ Platform["Start window tracker WebSocket policy"]:::init
+ end
- Decision -->|yes| WriteConfig["Write config + exit"]:::phase
- Decision -->|no| AppLifecycle["src/main/app-lifecycle.ts"]:::phase
+ Init --> Create["Create overlay window Establish IPC bridge Load Yomitan extension"]:::phase
- AppLifecycle --> Ready["src/main/startup-lifecycle.ts\nConfig · WebSocket · Tracker · Tokenizer · State"]:::phase
+ Create --> Loop
+ subgraph Loop["Runtime — event-driven"]
+ direction LR
+ Events["mpv · IPC · CLI shortcut events"]:::runtime
+ Dispatch["Route to service via composition layer"]:::runtime
+ State["Update state broadcast to renderer"]:::runtime
+ Events --> Dispatch --> State
+ end
- Ready --> Runtime["Runtime Modules\nipc · cli · overlay · subsync"]:::runtime
+ Loop -->|"app close"| Quit["Electron will-quit"]:::shutdown
+ Quit --> Teardown["Close mpv socket · unregister shortcuts Stop WebSocket & texthooker Destroy tracker · clean Anki state"]:::shutdown
- Runtime --> Overlay["Overlay & Mining"]:::runtime
- Runtime --> Subtitle["Subtitle Processing"]:::runtime
- Runtime --> SubsyncInt["Subsync & Jimaku"]:::runtime
-
- Runtime --> WillQuit["Electron will-quit"]:::shutdown
- WillQuit --> Cleanup["Service Teardown"]:::shutdown
+ style Init fill:#363a4f,stroke:#494d64,color:#cad3f5
+ style Loop fill:#363a4f,stroke:#494d64,color:#cad3f5
```
## Why This Design
diff --git a/docs/index.md b/docs/index.md
index cf45588..8efeeba 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -6,8 +6,8 @@ titleTemplate: Immersion Mining Workflow for MPV
hero:
name: SubMiner
- text: Built for Immersion Mining
- tagline: A self-contained MPV overlay for Japanese study. Look up words, mine cards, and enrich Anki without breaking playback flow.
+ text: Immersion Mining for MPV
+ tagline: Look up words, mine to Anki, and enrich cards with context — all without leaving the video.
image:
src: /assets/SubMiner.png
alt: SubMiner logo
@@ -18,80 +18,80 @@ hero:
- theme: alt
text: Mining Workflow
link: /mining-workflow
- - theme: alt
- text: Is This For Me?
- link: "#who-this-is-for"
features:
- icon:
src: /assets/mpv.svg
alt: mpv icon
title: Built for mpv
- details: Connects directly to mpv over IPC — tracks subtitles in real time, observes playback properties, and renders a self-contained overlay with everything bundled in a single application.
+ details: Connects via IPC to track subtitles in real time and render a self-contained overlay — everything bundled in a single application.
- icon:
src: /assets/yomitan-icon.svg
alt: Yomitan logo
title: Yomitan Integration
- details: Hover over any word in the subtitles to trigger Yomitan dictionary lookups — get instant definitions without leaving the video player.
+ details: Hover over any word in the subtitle overlay to trigger dictionary lookups — instant definitions without leaving the player.
- icon:
src: /assets/anki-card.svg
alt: Anki card icon
title: Anki Card Enrichment
- details: Add a word from Yomitan and SubMiner automatically updates the card with the sentence, audio clip, screenshot, and translation — no extra steps needed.
+ details: Add a word from Yomitan and SubMiner fills in the sentence, audio clip, screenshot, and translation automatically.
- icon:
src: /assets/dual-layer.svg
alt: Dual layer icon
- title: Dual-Layer Subtitle System
- details: Visible overlay with styled, interactive subtitles — plus an invisible layer that aligns with mpv's own subtitle rendering for seamless click-through lookup.
+ title: Dual-Layer Subtitles
+ details: Interactive visible overlay plus an invisible layer aligned with mpv's own rendering for seamless click-through lookup.
- icon:
src: /assets/highlight.svg
alt: Highlight icon
- title: N+1 Word Highlighting
- details: Highlights words you already know from your Anki deck, making it easy to spot new vocabulary and identify true N+1 sentences during immersion.
+ title: N+1 Highlighting
+ details: Marks words you already know from your Anki deck so you can spot new vocabulary and identify N+1 sentences at a glance.
- icon:
src: /assets/texthooker.svg
alt: Texthooker icon
title: Texthooker & WebSocket
- details: Built-in texthooker page that receives subtitles over WebSocket — use it as a clipboard inserter for Yomitan or connect external tools for real-time subtitle streaming.
+ details: Built-in texthooker page that receives subtitles over WebSocket — use it as a clipboard inserter or connect external tools.
- icon:
src: /assets/subtitle-download.svg
alt: Subtitle download icon
title: Subtitle Download & Sync
- details: Search and download Japanese subtitles from Jimaku, then sync them to the audio with alass or ffsubsync — all from within the player.
+ details: Search and download Japanese subtitles from Jimaku, then sync to audio with alass or ffsubsync — all from within the player.
- icon:
src: /assets/keyboard.svg
alt: Keyboard icon
- title: Keyboard-Driven Workflow
- details: Mine sentences, copy subtitles, cycle display modes, and trigger field grouping — all from configurable keyboard shortcuts without touching the mouse.
+ title: Keyboard-Driven
+ details: Mine sentences, copy subtitles, cycle display modes, and trigger field grouping — all from configurable shortcuts.
---
-
-
-## What SubMiner Is For
-
-SubMiner is for people who learn Japanese by watching subtitled content in mpv and want a low-friction mining loop:
-
-- stay inside the video while looking up words
-- send mined content to Anki quickly
-- keep media context (audio, screenshot, timestamp, subtitle context) attached to each card
-- reduce tool switching between player, dictionary, and card workflow
-
-
-
-
-
-## Project Goals
-
-
-
-
1. Keep Immersion Continuous
-
Minimize context switching by making lookup and mining happen directly over mpv subtitles.
-
-
-
2. Preserve Card Quality
-
Attach sentence context, audio, image, and translation so mined cards stay reviewable and useful long-term.
Offer defaults that work out of the box, while still letting advanced users shape behavior around their note type and setup.
-
-
-
5. Evolve Safely
-
Use a modular TypeScript codebase and automated tests so features can ship faster without breaking core mining behavior.
-
-
-
-
-
-
-
-## See It in Action
-
-SubMiner sits as a transparent overlay on top of mpv. Subtitles appear as interactive, clickable text — click a word to look it up with Yomitan, then add it to Anki with one click.
-
-
-
-
-
-
-
-## Who This Is For
-
-- learners using mpv as their main immersion player
-- users who already rely on Yomitan + AnkiConnect
-- miners who care about preserving context on cards, not just raw words
-
-SubMiner is likely overkill if you only want lightweight lookup without card enrichment, overlay controls, or integrated workflow tooling.
-
-
-
## How It Works
@@ -212,7 +158,7 @@ SubMiner is likely overkill if you only want lightweight lookup without card enr
02
Look Up
-
Hover over a word in the subtitle overlay and hold Shift to trigger a Yomitan dictionary lookup.
+
Hover over a word in the subtitle overlay and hold Shift to trigger a Yomitan lookup.
03
@@ -227,3 +173,14 @@ SubMiner is likely overkill if you only want lightweight lookup without card enr