update readme/docs

This commit is contained in:
2026-02-23 01:41:52 -08:00
parent cbed5f1376
commit 4f02d7db9c
11 changed files with 179 additions and 40 deletions

View File

@@ -87,6 +87,7 @@ export default {
items: [
{ text: 'Building & Testing', link: '/development' },
{ text: 'Architecture', link: '/architecture' },
{ text: 'IPC + Runtime Contracts', link: '/ipc-contracts' },
],
},
],

View File

@@ -25,6 +25,7 @@ make docs-preview # Preview built site at http://localhost:4173
- [Anki Integration](/anki-integration) — AnkiConnect setup, field mapping, media generation, field grouping
- [Jellyfin Integration](/jellyfin-integration) — Optional Jellyfin auth, cast discovery, remote control, and playback launch
- [Immersion Tracking](/immersion-tracking) — SQLite schema, retention/rollup policies, query templates, and extension points
- [Performance & Tuning](/troubleshooting#performance-and-resource-impact) — Resource usage and practical low-impact profile
- [JLPT Vocabulary](/jlpt-vocab-bundle) — Bundled term-meta bank for JLPT level underlining and frequency highlighting
- [MPV Plugin](/mpv-plugin) — Chord keybindings, subminer.conf options, script messages
- [Troubleshooting](/troubleshooting) — Common issues and solutions by category
@@ -33,3 +34,4 @@ make docs-preview # Preview built site at http://localhost:4173
- [Building & Testing](/development) — Build commands, test suites, contributor notes, environment variables
- [Architecture](/architecture) — Service-oriented design, composition model, renderer module layout
- [IPC + Runtime Contracts](/ipc-contracts) — Main/renderer IPC contracts and contributor onboarding

View File

@@ -310,14 +310,18 @@ flowchart LR
Warmups["Background<br/>warmups"]:::phase
Warmups --> W1["MeCab"]:::warmup
Warmups --> W2["Yomitan"]:::warmup
Warmups --> W3["JLPT + freq<br/>dictionaries"]:::warmup
Warmups --> W4["Jellyfin"]:::warmup
Warmups --> W5["Discord"]:::warmup
Warmups --> W6["AniList"]:::warmup
subgraph WarmupGroup[" "]
direction TB
W1["MeCab"]:::warmup
W2["Yomitan"]:::warmup
W3["JLPT + freq<br/>dictionaries"]:::warmup
W4["Jellyfin"]:::warmup
W5["Discord"]:::warmup
W6["AniList"]:::warmup
W1 ~~~ W2 ~~~ W3 ~~~ W4 ~~~ W5 ~~~ W6
end
W1 & W2 & W3 & W4 & W5 & W6 --> Loop
Warmups --> WarmupGroup
subgraph Loop["Runtime — event-driven"]
direction TB
@@ -329,6 +333,10 @@ flowchart LR
Process --> Broadcast["Update AppState<br/>broadcast to windows"]:::runtime
end
WarmupGroup --> Loop
style WarmupGroup fill:transparent,stroke:none
Loop -->|"quit signal"| Quit["will-quit"]:::shutdown
Quit --> T1["Tray · config watcher<br/>global shortcuts"]:::shutdown
@@ -354,6 +362,7 @@ flowchart LR
- Add behavior to an existing service in `src/core/services/*` or create a focused runtime module under `src/main/runtime/*`; avoid ad-hoc logic in `main.ts`.
- Add new cross-process channels in `src/shared/ipc/contracts.ts` first, validate payloads in `src/shared/ipc/validators.ts`, then wire handlers in IPC runtime modules.
- See also the contributor IPC onboarding page: [IPC + Runtime Contracts](/ipc-contracts).
- If change spans startup/overlay/mpv/integration wiring, prefer composing through `src/main/runtime/domains/*` + `src/main/runtime/composers/*` rather than direct wiring in `main.ts`.
- Keep service APIs explicit and narrowly scoped, and preserve existing CLI flag / IPC channel behavior unless the change is intentionally breaking.
- Add or update focused tests (including malformed-payload IPC tests) when runtime boundaries or contracts change.

View File

@@ -1,3 +1,7 @@
---
outline: [2, 3]
---
# Configuration
Settings are stored in `$XDG_CONFIG_HOME/SubMiner/config.jsonc` (or `~/.config/SubMiner/config.jsonc` when `XDG_CONFIG_HOME` is unset).

View File

@@ -43,12 +43,13 @@ Download the latest AppImage from [GitHub Releases](https://github.com/ksyasuda/
```bash
# Download and install AppImage
wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/SubMiner-0.1.0.AppImage -O ~/.local/bin/SubMiner.AppImage
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/SubMiner.AppImage -O ~/.local/bin/SubMiner.AppImage
chmod +x ~/.local/bin/SubMiner.AppImage
# Download subminer wrapper script
wget https://github.com/ksyasuda/SubMiner/releases/download/v0.1.0/subminer -O ~/.local/bin/subminer
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer -O ~/.local/bin/subminer
chmod +x ~/.local/bin/subminer
```
The `subminer` wrapper uses a Bun shebang (`#!/usr/bin/env bun`), so [Bun](https://bun.sh) must be installed and available on `PATH`.
@@ -135,22 +136,7 @@ Ensure `mecab` is available on your PATH when launching SubMiner.
binary_path=/Applications/SubMiner.app/Contents/MacOS/subminer
```
## Windows
Windows support is available through the mpv plugin. Set the binary and socket path in `subminer.conf`:
```ini
binary_path=C:\\Program Files\\subminer\\subminer.exe
socket_path=\\\\.\\pipe\\subminer-socket
```
Launch mpv with:
```bash
mpv --input-ipc-server=\\\\.\\pipe\\subminer-socket video.mkv
```
## MPV Plugin (Optional)
## MPV Plugin (Recommended)
The Lua plugin provides in-player keybindings to control the overlay from mpv. It communicates with SubMiner by invoking the binary with CLI flags.
@@ -160,7 +146,7 @@ mpv must be launched with `--input-ipc-server=/tmp/subminer-socket` for SubMiner
```bash
# Option 1: install from release assets bundle
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer-assets-0.1.0.tar.gz -O /tmp/subminer-assets.tar.gz
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer-assets.tar.gz -O /tmp/subminer-assets.tar.gz
tar -xzf /tmp/subminer-assets.tar.gz -C /tmp
mkdir -p ~/.config/SubMiner
cp /tmp/config.example.jsonc ~/.config/SubMiner/config.jsonc
@@ -171,7 +157,7 @@ cp /tmp/plugin/subminer.conf ~/.config/mpv/script-opts/
# make install-plugin
```
## Rofi Theme (Optional)
## Rofi Theme (Linux Only)
SubMiner ships a default rofi theme at `assets/themes/subminer.rasi`.

47
docs/ipc-contracts.md Normal file
View File

@@ -0,0 +1,47 @@
# IPC + Runtime Contracts
## Core Surfaces
- `src/shared/ipc/contracts.ts`: canonical channel names and payload contracts
- `src/shared/ipc/validators.ts`: runtime payload validation/parsing
- `src/preload.ts`: renderer bridge to approved IPC endpoints
- `src/main/ipc-runtime.ts`: main-process registration and handler routing
- `src/core/services/ipc.ts`: service-level invoke handling and guardrails
- `src/core/services/anki-jimaku-ipc.ts`: integration-specific IPC boundary
- `src/main/cli-runtime.ts`: CLI/runtime command boundary
## Contract Rules
- Use shared contract constants; avoid ad-hoc literal channel strings.
- Validate `invoke` payloads before domain/service logic.
- Return structured failures (`{ ok: false, error }`) where possible.
- Keep payloads narrow and explicit.
- Update contracts, validators, preload types, and handlers in the same change when shape changes.
## Add a New IPC Action
1. Add channel in `src/shared/ipc/contracts.ts`.
2. Add or extend validator in `src/shared/ipc/validators.ts`.
3. Expose typed bridge method in `src/preload.ts`.
4. Register handler in `src/main/ipc-runtime.ts` (or relevant domain runtime module).
5. Add tests for valid and malformed payload cases in `src/core/services/*`.
6. Update renderer tests when behavior or state transitions change.
## Runtime State Notes
- Prefer runtime/domain composition via `src/main/runtime/composers/*` and `src/main/runtime/domains/*`.
- Route shared mutable state updates through transition helpers in `src/main/state.ts` for migrated domains.
- Keep IPC handlers thin; avoid embedding business logic in transport wiring.
## Troubleshooting
- Unknown payload in handler: confirm validator is applied before handler/service call.
- Renderer invoke fails: verify preload bridge method and channel registration.
- Contract drift: compare shared contract, validator, preload bridge, and main handler signatures together.
## Related Docs
- [Architecture](/architecture)
- [Development](/development)
- [Configuration](/configuration)
- [Troubleshooting](/troubleshooting)

View File

@@ -15,7 +15,7 @@ Watch video → See subtitle → Click word → Yomitan lookup → Add to Anki
## Subtitle Delivery Path (Startup + Runtime)
SubMiner now prioritizes subtitle responsiveness over heavy initialization:
SubMiner prioritizes subtitle responsiveness over heavy initialization:
1. The first subtitle render is **plain text first** (no tokenization wait).
2. Tokenized enrichment (word spans, known-word flags, JLPT/frequency metadata) is applied right after parsing completes.

View File

@@ -6,12 +6,13 @@ The SubMiner mpv plugin (`subminer.lua`) provides in-player keybindings to contr
```bash
# From release bundle:
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer-assets-0.1.0.tar.gz -O /tmp/subminer-assets.tar.gz
wget https://github.com/ksyasuda/SubMiner/releases/latest/download/subminer-assets.tar.gz -O /tmp/subminer-assets.tar.gz
tar -xzf /tmp/subminer-assets.tar.gz -C /tmp
mkdir -p ~/.config/SubMiner
cp /tmp/config.example.jsonc ~/.config/SubMiner/config.jsonc
cp /tmp/plugin/subminer.lua ~/.config/mpv/scripts/
cp /tmp/plugin/subminer.conf ~/.config/mpv/script-opts/
# Or from source checkout: make install-plugin
```

View File

@@ -21,6 +21,81 @@ SubMiner retries the connection automatically with increasing delays (200 ms, 50
- 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`, `whisper` fallback path)
- `ankiConnect` enrichment and frequent polling
### 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`
2. Reduce rendering pressure:
- lower `subtitleStyle.fontSize`
- keep overlay complexity minimal during heavy CPU periods
3. Reduce media overhead:
- keep `ankiConnect.media.imageType` set to `static` (avoid animated AVIF unless needed)
- lower `ankiConnect.media.imageQuality`
- reduce `ankiConnect.media.maxMediaDuration`
4. 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)
- prefer YouTube `--mode automatic` over `preprocess` on low-resource systems
### Practical low-impact profile
```json
{
"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.