You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: document font subsetting, config v3, dependency resolution, and GUI changes
Update README (EN/CN) and the architecture, roadmap, security, and troubleshooting docs to reflect font subsetting (referenced/subset modes), config schema v3 with ffmpeg/notifications sections, external dependency resolution, snapshot digest verification, and the new GUI controls.
PlexMuxy safely batches video, external audio, ASS/SSA subtitles, and font attachments into Matroska files for Plex. The CLI and desktop GUI use the same planning and execution service.
Useful job overrides include `--output-dir`, `--output-suffix`, `--name-strategy`, `--name-template`, `--extra-dir`, `--overwrite`, and `--cleanup`.
67
+
Useful job overrides include `--output-dir`, `--output-suffix`, `--name-strategy`, `--name-template`, `--extra-dir`, `--font-mode`, `--overwrite`, and `--cleanup`. For example, `--font-mode subset` enables font subsetting for that plan.
60
68
61
69
## Configuration
62
70
@@ -89,6 +97,10 @@ Important defaults:
89
97
90
98
Parallel mux jobs are intentionally limited to 1–4 and default to 1. The old `thread_count` key is accepted only for migration. Archive limits apply before ZIP/7z extraction; uninspectable RAR archives require explicit permission.
91
99
100
+
The desktop “Environment configuration” view is persistent and separate from job options. It shows environment-variable and `PATH` discovery first, then offers a native file picker for `mkvmerge`, `ffmpeg`, or `unrar` when automatic discovery fails. Windows builds opt into Per-Monitor V2 awareness before creating native windows so the WebView and file dialogs follow system scaling on high-DPI and mixed-monitor setups.
101
+
102
+
Windows job notifications can be enabled on that page. The current native Windows Shell backend covers completed, failed, and cancelled jobs, and notification failures never change a mux result. Action buttons, application activation, and durable notification-center identity require a future installer/application-identity integration with the Windows App SDK.
103
+
92
104
## Matching
93
105
94
106
Each subtitle or external audio file is assigned once using this priority: exact stem (1.0), normalized title (0.85), normalized episode identity (0.70), and optional controlled single-video movie fallback. Episode parsing supports `[1]`, `[100]`, `S01E01`, `S01EP01`, `E01`, `EP01`, `.01.`, `SP01`, `Special`, and `OVA`.
@@ -97,7 +109,11 @@ Equal best candidates become `ambiguous_match` and are skipped. Low-confidence c
97
109
98
110
## Fonts and source tracks
99
111
100
-
`font.mode=all` preserves the compatibility-first behavior. `referenced` parses ASS/SSA style font names and `\fn` overrides, matches font metadata, and follows `missing_font_action`. `subset` currently falls back to referenced full fonts and reports that decision; it never emits a knowingly incomplete subset.
112
+
`font.mode=all` preserves the compatibility-first behavior. `referenced` uses the structural ASS/SSA parser and internal font names to select complete fonts. `subset` performs real glyph subsetting: it follows dynamic `Format` fields plus Style and override state (`\fn`, `\r`, `\b`, `\i`, `\p`, and `\t(...)`), enumerates every TTF/OTF/TTC/OTC face, and deterministically matches internal family, weight, italic, and cmap metadata. Temporary subtitles rewrite only validated families to `PMX_<hash>` aliases; source subtitles and fonts are never modified.
113
+
114
+
Every plan in a batch is prepared and revalidated in an execution-scoped workspace before any `mkvmerge` process starts. Identical subset work is cached for that execution and the workspace is removed after success, failure, or cancellation. If FontTools cannot safely subset a matched family, the default policy attaches that family’s complete source faces without rewriting its name. Missing or ambiguous fonts, missing glyphs, structurally unsafe ASS, and ambiguous BOM-less GB18030/CP932 input are never silently treated as safe subsets. Configure `missing_font_action` and `subset_failure_action` for the permitted skip, fail-job, or full-font behavior.
115
+
116
+
Output verification checks the expected attachment file names and MIME types as well as track properties and counts.
101
117
102
118
Source container tracks are read with `mkvmerge -J` and shown in plans. The 0.2 product decision is to preserve all source tracks. Filter configuration is reserved for explicit future use; unknown languages and untitled tracks must remain included.
The adapters validate user payloads and call `plexmuxy.service`; they do not implement mux policy. `scanner` classifies files without following symlinks or hidden paths by default. `matcher` globally assigns each candidate so a file cannot silently attach to two videos. `planner` creates deterministic outputs, tracks, attachment intent, and cleanup candidates.
16
18
17
-
`snapshot` records the normalized config plus size and nanosecond modification time for every existing input. Execution validates it and rechecks output appearance. Deserialization requires absolute paths and reconstructs typed models; output paths are recomputed from the saved configuration to reject edited plan paths.
19
+
`snapshot` records the normalized config plus size and nanosecond modification time for every input. Schema 2 also records SHA-256 digests for subtitles, fonts, and font archives, together with deterministic subset intent; generated workspace paths are never serialized. Execution validates the snapshot and rechecks output appearance. Deserialization requires absolute paths and reconstructs typed models; output paths are recomputed from the saved configuration to reject edited plan paths.
18
20
19
-
`muxer` owns the `mkvmerge` subprocess so cancellation can terminate it. It never writes directly to the final pathname. `verify_mux_output` parses `mkvmerge -J`, distinguishes execution and verification error codes, and verifies expected structure. `cleanup` operates once, after all jobs settle, using dependency groups for shared files.
21
+
Subset execution is deliberately two-phase. `ass_analysis`, `font_catalog`, and `font_matching` produce immutable intent during planning. After snapshot validation, `font_prepare` materializes archive members, subsets every selected face, validates cmap/name/style metadata, and rewrites temporary ASS/SSA files. Every plan must finish preparation before the bounded mux pool starts. `SubsetWorkspace` owns all generated files and removes them only after every mux worker exits.
20
22
21
-
The GUI `PlexMuxyApi` starts daemon-backed jobs and exposes `start_job`, `get_job_status`, `get_job_report`, and `cancel_job`. Progress events are plain core objects; the core package has no GUI dependency.
23
+
`muxer` owns the `mkvmerge` subprocess so cancellation can terminate it. It never writes directly to the final pathname. Prepared runtime plans replace only subtitle and attachment inputs while results retain the original immutable plan. `verify_mux_output` parses `mkvmerge -J`, distinguishes execution and verification error codes, and verifies expected structure, attachment names, and MIME types. `cleanup` operates once, after all jobs settle, using dependency groups for shared files.
24
+
25
+
The GUI `PlexMuxyApi` starts daemon-backed jobs and exposes `start_job`, `get_job_status`, `get_job_report`, and `cancel_job`. Progress events include preparation, family, mux, verification, and cleanup phases; the core package has no GUI dependency. Persistent dependency paths and the Windows notification preference live in config version 3 and are not job overrides.
22
26
23
27
Source audio filtering is deliberately not enabled in 0.2. Plans expose source track metadata, but the preservation rule is the product default. Any future filter must be opt-in, list kept/excluded tracks with reasons, and retain unknown metadata by default.
The 0.2 scope intentionally preserves source tracks and full/referenced fonts. Proposed follow-up issues:
3
+
PlexMuxy now includes structural ASS/SSA analysis, real FontTools glyph subsetting, deterministic alias rewriting, TTC/OTC face handling, and execution-scoped cache/fallback. Remaining proposed follow-up issues:
4
4
5
-
- ASS/SSA font alias analysis and richer missing-font reporting.
6
-
- True glyph subsetting with fontTools, including CJK, shaping, OpenType features, TTC collections, and deterministic full-font fallback.
5
+
- Optional HarfBuzz repacking and FFmpeg/libass golden-frame parity fixtures for more scripts and font formats.
6
+
- Versioned persistent subset caching after FontTools/HarfBuzz compatibility keys are defined.
7
+
- Windows App SDK notifications with installer-provided application identity, activation, and action buttons.
7
8
- Source audio preview and explicit commentary/language/title filters; unknown tracks must be kept.
8
9
- Multi-directory queue, persisted job history, and safe manual plan editing.
9
-
- Internationalized CLI/GUI resources and optional update checks.
10
+
- Internationalized CLI resources and optional update checks.
10
11
- Optional Plex library scan integration isolated from the mux transaction.
Copy file name to clipboardExpand all lines: docs/security.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,8 +6,10 @@ PlexMuxy treats source media as irreplaceable.
6
6
- Existing outputs require overwrite opt-in. Muxing still uses a unique temporary path, so a failed subprocess cannot corrupt the previous output.
7
7
- Delete cleanup and font-directory deletion require confirmation. Verification failure, cancellation, partial batch failure, and missing attachments suppress cleanup.
8
8
-`move` never overwrites an `Extra` file; it creates `name (1).ext`, `name (2).ext`, and so on.
9
-
- Saved plans are untrusted input. Absolute paths, tracked file metadata, recomputed output paths, configuration hashes, attachment containment, and newly appeared outputs are checked before execution.
9
+
- Saved plans are untrusted input. Absolute paths, tracked file metadata, recomputed output paths, configuration hashes, attachment containment, newly appeared outputs, and SHA-256 digests for subtitles/fonts/font archives are checked before execution.
10
10
- ZIP/7z members are checked for path traversal and configurable size/count/depth limits before extraction. RAR is denied by default when metadata cannot be safely inspected.
11
+
- Subset fonts and rewritten subtitles are created only under an execution-scoped system temporary directory, written through temporary names, reopened and validated, and removed after every mux worker exits. They are never added to user cleanup candidates.
12
+
- Ambiguous font matches, missing glyphs, unsafe ASS/SSA structures, and ambiguous legacy encodings cannot silently enter the subset pipeline. Full-font fallback is limited to explicit policy branches.
11
13
- Diagnostic archives contain no media and redact configured directories.
12
14
13
15
Treat any report of unintended overwrite, move, or deletion as release-blocking. Stop distribution, mark the release as affected, publish a warning, reproduce using copies, and ship a patch only after the data-safety regression suite passes.
Copy file name to clipboardExpand all lines: docs/troubleshooting.md
+16-2Lines changed: 16 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
## `MKVMERGE_NOT_FOUND`
4
4
5
-
Install MKVToolNix, add `mkvmerge` to `PATH`, or set the full executable/directory in `mkvmerge.path`. Run `plexmuxy diagnostics --output diagnostics.zip` to record the detected version.
5
+
Install MKVToolNix, add `mkvmerge` to `PATH`, set the executable/directory in `mkvmerge.path`, or use GUI → Environment configuration → mkvmerge → Browse. An invalid explicit path is reported instead of silently falling back to a different binary. Run `plexmuxy diagnostics --output diagnostics.zip` to record the detected version.
6
6
7
7
## No plan was generated
8
8
@@ -28,6 +28,20 @@ Pass `--yes` only after reviewing the plan. The GUI presents a destructive-actio
28
28
29
29
Corrupt archives, resource-limit violations, path traversal, and uninspectable RAR files are reported. Extract RAR fonts manually into `Fonts`, or explicitly opt into uninspected extraction only for trusted archives.
30
30
31
+
## `font_subset_blocked` or `FONT_SUBSET_FAILED`
32
+
33
+
Planning blocks a video when a font is missing or ambiguous, a selected face lacks required characters, or the ASS/SSA structure cannot be analyzed and rewritten safely. BOM-less byte sequences that are both valid GB18030 and CP932 but decode differently are intentionally rejected. Use a correctly encoded/BOM-tagged subtitle, install the exact referenced font, or choose a documented `missing_font_action`; do not rename an unrelated font to bypass matching.
34
+
35
+
At execution time, `FONT_SUBSET_FAILED` means a previously matched source changed or a verified runtime subset/rewrite could not be produced. The default `subset_failure_action=fallback-full` applies only to a concrete matched family that cannot be subset safely. `skip-video` isolates the affected video and `fail-job` stops the batch before any mux process starts.
36
+
37
+
## A diagnostic path did not fit in the title bar
38
+
39
+
Transient results such as diagnostics export paths now appear in a wrapping toast with an “Open folder” action. The title bar is reserved for persistent state such as a missing required dependency and an active job.
40
+
41
+
## Windows notification is unavailable
42
+
43
+
Notifications require the Windows GUI build, its packaged ICO, and the pywebview Windows runtime. Use the test button on Environment configuration. The setting is disabled when capability detection fails; mux completion is unaffected. The current backend is a Windows Shell notification-area balloon, not an actionable Windows App SDK notification with application activation.
44
+
31
45
## GUI does not start
32
46
33
-
Install `plexmuxy[gui]`. On Windows, install the WebView2 Evergreen Runtime. The CLI remains usable without GUI packages.
47
+
Install `plexmuxy[gui]`. On Windows, install the WebView2 Evergreen Runtime. The CLI remains usable without GUI packages. If file dialogs scale incorrectly, use the packaged GUI whose manifest requests Per-Monitor V2 awareness rather than launching an older wrapper executable.
0 commit comments