This document walks the pipeline a frame travels through, names every module it touches, and points new contributors at the right file for a given change. Pairs with ROADMAP.md and CHANGELOG.md.
Concrete and up to date as of the v3.41.0 pass. Keep this in sync when modules move.
.
|-- VideoSubtitleRemover.py # Entry point (thin launcher -> gui.app).
|-- setup.py # Validated venv bootstrap with atomic setup reports.
|-- build_exe.bat # Local PyInstaller build, evidence, release staging.
|-- requirements.txt # Pinned and advisory dependency floors.
|-- dependency_profiles.json # Reviewed CPU/NVIDIA/DirectML profile manifest.
|-- Run_VSR_Pro.bat # Windows launcher with profile verification and repair.
|-- Run_VSR_Pro_Debug.bat # Visible-console launcher with profile repair.
|-- Run_VSR_Pro.ps1 # PowerShell launcher with profile verification and repair.
|-- gui/
| |-- __init__.py # GUI subpackage re-exports.
| |-- app.py # Tk shell, shared state, queue model, settings.
| |-- config.py # APP_VERSION, QueueItem, GUI ProcessingConfig, settings I/O.
| |-- dialog_layout.py # Work-area fitting and scrollable dialog bodies.
| |-- direction.py # Logical-to-physical RTL mirror for Tk options.
| |-- failure_copy.py # Stable English queue-row failure and status copy.
| |-- job_supervisor.py # Parent-side supervisor for isolated queue jobs.
| |-- layout_build.py # Builder mixin: header, settings, queue, preview.
| |-- layout_helpers.py # Shared layout primitives for the builder mixins.
| |-- layout_responsive.py # Responsive / stacked layout mixin.
| |-- mask_correction_controller.py # Mask paint/erase review and selective rerun.
| |-- onboarding.py # First-run onboarding modal mixin.
| |-- preview_controller.py # Preview timeline, proxy planning, A/B compare, live frames, zoom.
| |-- process_job.py # Windows job object containment for worker process trees.
| |-- processing_controller.py # Queue worker, pause/stop, reports, notifications.
| |-- quality_controller.py # Quality review, retry, batch-report helpers.
| |-- queue_view.py # Queue table rendering and row state mixin.
| |-- region_controller.py # Region editor: rects, spans, keyframes, polygons.
| |-- release_probe.py # Packaged scaling, contrast, RTL, and dialog release probe.
| |-- settings_controller.py # Settings widgets, presets, mode selection.
| |-- single_instance.py # One interactive instance per user session.
| |-- state_lock.py # Cross-process lock for the shared user state files.
| |-- support_controller.py # Support bundle, model cache, log panel, About.
| |-- theme.py # Design tokens, colors, spacing, typography, text scale.
| |-- track_plan_controller.py # Pre-run track plan scan and review dialog.
| |-- utils.py # File helpers, media type checks, formatting.
| `-- widgets.py # Custom controls (ModernButton/Toggle/Slider/Picker/...).
|-- backend/
| |-- __init__.py # Lazy re-exports SubtitleRemover and friends.
| |-- _clean_ref_mixin.py # Clean-reference plate handling.
| |-- _encode_mixin.py # Encode / mux / audio stages of the processor.
| |-- _finalize_mixin.py # Finalize, output contract, post-restore, sidecar.
| |-- _frame_loop_mixin.py # Per-batch stages of the frame loop.
| |-- _frame_loop_types.py # Frame-loop window, context, and batch carrier.
| |-- _inpaint_mixin.py # Inpainter execution, result validation, OOM recovery.
| |-- _pipeline_mixin.py # process_video and process_image, end to end.
| |-- _quality_mixin.py # Quality-report stages of the processor.
| |-- _srt_mixin.py # Tracked OCR consensus and SRT export stages.
| |-- a11y.py # Accessibility metadata helpers.
| |-- adapter_manifest.py # Optional model pins, artifact hashes, provenance records.
| |-- atomic_replace.py # Journalled multi-file replacement and recovery.
| |-- batch_report.py # JSON + Markdown batch summary and output sidecars.
| |-- build_profile.py # Dependency profile a frozen build was made from.
| |-- cache_inventory.py # Cache info/clean and portable model-cache bundles.
| |-- cli.py # argparse entry point and batch driver.
| |-- config.py # Backend ProcessingConfig, InpaintMode, coercers.
| |-- config_schema.py # Canonical config schema and settings migration.
| |-- container_payload.py # Container metadata/chapters/attachment mapping.
| |-- crash_reporter.py # Opt-in crash reporter (allowlisted minimal events).
| |-- decode_accel.py # Hardware decode hints (D3D11/VAAPI/MFX/PyNv).
| |-- dependency_caps.py # Dependency ceilings and execution-provider lanes.
| |-- dependency_profiles.py # Locked profiles plus package, import, pip, and provider verification.
| |-- detection.py # OCR cascade, selectable engines, execution provenance.
| |-- detection_geometry.py # OCR boxes, polygons, text, confidence, track IDs.
| |-- device_provider.py # Device strategy and inpainter construction.
| |-- encoder.py # Output codec probing and HW encoder selection.
| |-- execution_provenance.py # Execution and loaded-model identity record.
| |-- failure_reason.py # Closed-set failure classification for rows and reports.
| |-- ffmpeg_profiles.py # FFmpeg capability profiles and security probe.
| |-- frozen_matte.py # Freeze an approved matte as a reusable input.
| |-- hdr.py # Color metadata preservation and HDR handling.
| |-- i18n.py # gettext localisation runtime.
| |-- import_safety.py # Crash-safe optional-module import probes.
| |-- inpainter_registry.py # In-process inpainter discovery registry.
| |-- inpainters_diffusion.py # Opt-in diffusion adapter scaffolds.
| |-- inpainters_onnx.py # ONNX Runtime inpaint session helpers.
| |-- io.py # Capture, ffprobe, intermediate writers, PrefetchReader.
| |-- job_worker.py # Child-process entry for one isolated queue job.
| |-- karaoke_flow.py # Karaoke optical-flow grouping helper.
| |-- keep_awake.py # Scoped Windows sleep hold for the length of a job.
| |-- language_support.py # GUI picker scope vs. OCR engine language facts.
| |-- mask_corrections.py # Ordered add/subtract mask corrections.
| |-- mask_free_benchmark.py # Mask-free removal benchmark harness.
| |-- matte_interchange.py # Lossless matte export / import / compose.
| |-- model_downloads.py # First-run guidance and outbound-model inventory.
| |-- model_fetch.py # Consented, hash-verified download of optional model weights.
| |-- model_file_format.py # Identifies a model file from its bytes, never its name.
| |-- model_hashes.py # Vendored SHA-256 hashes and chunked verifier.
| |-- nle_sidecar.py # EDL / FCPXML sidecar export.
| |-- ocr_benchmark.py # OCR engine recall / precision benchmark.
| |-- ocr_fix.py # Per-language OCR replace lists for exported SRT.
| |-- ocr_variants.py # Canonical PaddleOCR model families and aliases.
| |-- ocr_vlm.py # Optional VLM detectors (Florence-2, Qwen2.5-VL).
| |-- onnx_model_info.py # ONNX opset audit and Windows ML probe.
| |-- onnxruntime_cuda.py # CUDA preload status for ONNX Runtime.
| |-- opencv_ocr.py # PP-OCRv6 via OpenCV 5 DNN and the engine contract.
| |-- output_contract.py # Frozen per-job output policy.
| |-- output_quality_preflight.py # Pre-run output quality warnings.
| |-- paddle_compat.py # PaddleOCR 2.x / 3.x API compatibility layer.
| |-- post_restore.py # Post-inpaint temporal smoothing and burn-in.
| |-- preprocess.py # Deinterlacing and keyframe enumeration.
| |-- presets.py # Shared preset library (GUI + CLI).
| |-- processor.py # Frame loop plus the legacy re-export / CLI shim.
| |-- provider_benchmark.py # Measured cost of one provider lane on one clip.
| |-- proxy_workflow.py # Proxy-encode workflow for large files.
| |-- quality.py # PSNR / SSIM / VMAF and temporal metrics.
| |-- quality_gate.py # Graduated quality gate with a remediation ladder.
| |-- reference_corpus.py # Exact-profile reference-clip regression harness.
| |-- reference_fill.py # Clean-plate reference fill.
| |-- region_editing.py # Region geometry edit / undo primitives.
| |-- region_keyframes.py # Interpolated moving-region keyframe tracks.
| |-- release_staging.py # Atomic, version-derived release artifact set.
| |-- release_verification.py # Local PyInstaller release evidence writer.
| |-- remote_model_policy.py # Gate for trust_remote_code / torch.hub.
| |-- removal_verification.py # Re-detects text in the repaired region to prove removal.
| |-- remux.py # Soft-subtitle strip / keep remux paths.
| |-- resume_checkpoint.py # Crash-resume and pause checkpoints.
| |-- safe_image.py # Bounded image reads.
| |-- security_checks.py # Runtime safety checks (libpng and OpenCV FFmpeg inventory).
| |-- segmentation.py # Optional SAM 2 / MatAnyone / CoTracker adapters.
| |-- static_logo_benchmark.py # Static-logo removal benchmark harness.
| |-- subprocess_policy.py # Hidden, bounded, cancellable child processes.
| |-- subtitle_translation.py # SRT parsing, providers, translated export.
| |-- support_bundle.py # Redacted diagnostics zip export.
| |-- temporal_profile.py # Mask-aware temporal regression metrics and fixtures.
| |-- tensorrt_compile.py # Optional TensorRT engine compilation.
| |-- track_plan.py # Reviewable pre-run text track plans.
| |-- tracking.py # Stable OCR identities, pHash reuse, karaoke grouping.
| |-- update_check.py # Startup version check (opt-in).
| |-- vapoursynth_bridge.py # VapourSynth bridge (opt-in).
| |-- webvtt.py # Loss-aware WebVTT parse / translate / serialize.
| |-- whisper_fallback.py # Whisper-based timing for OCR-empty speech.
| `-- work_directory.py # End-to-end scratch / storage policy.
| `-- inpainters/
| |-- __init__.py # Mode routing and shared inpainter exports.
| |-- _common.py # BaseInpainter, feathering, edge-ring match.
| |-- auto.py # Per-scene STTN / ProPainter motion routing.
| |-- external.py # VSR_EXTERNAL_INPAINTER bridge.
| |-- lama.py # ONNX > OpenCV 5 DNN > PyTorch opt-in > cv2.
| |-- propainter.py # TBE plus LaMa residual refinement.
| `-- sttn.py # TBE (Temporal Background Exposure).
|-- scripts/ # Build, i18n, and doc tooling.
|-- tools/ # Local probes (smoke, UI scaling).
|-- installer/ # NSIS installer sources.
|-- tests/ # Unit, hardening, and GUI suites.
`-- docs/ # Architecture and corpus guides.
gui/app.pyowns the Tk shell, shared state, settings variables, queue model, and the publicVideoSubtitleRemoverAppsurface. The widget construction itself lives in the layout mixins (gui/layout_build.py,gui/layout_responsive.py,gui/layout_helpers.py,gui/queue_view.py,gui/onboarding.py), which compose onto the app exactly like the controller mixins. Put new widget-building code in a mixin, not inapp.py. The default shell is a command-first workbench: one compact command strip sits above the preview/inspector split, and the persistent queue is rendered as a dense table below it. Advanced controls remain progressively disclosed in the inspector rather than competing with the primary workflow.gui/processing_controller.pyowns queue processing, pause/stop orchestration, per-item backend dispatch, progress/taskbar updates, report preparation, and completion notifications.gui/preview_controller.pyowns preview placeholders, the selected-time timeline, proxy scene planning, live frames, mask review, A/B compare, test-cleanup previews, and preview zoom. Manual-only mask previews rasterize the saved shapes without constructing or running an OCR detector. The region editor lives ingui/region_controller.pyand mask correction ingui/mask_correction_controller.py; both build into a scrollable dialog body fromgui/dialog_layout.pyso they reflow at high text scale.gui/quality_controller.pyowns batch-summary dialogs, source-aware quality warnings, quality-review worklists, retry-with-suggested-settings, and batch report file opening/writing.gui/support_controller.pyowns the log panel, support bundle export, model-cache import/export, backend-status panel, and About dialog.gui/widgets.pycontains all custom controls:ModernButton,ModernToggle,ModernSlider,SegmentedPicker,ModernProgressBar,DragDropFrame,QueueItemWidget,Toast,Tooltip, and themed utility functions.gui/config.pyis the single source of truth forAPP_VERSION, the GUIProcessingConfigdataclass,QueueItem, settings load/save/migrate, and preset import/export.backend/config.pyowns the backendProcessingConfig,InpaintModeenum, coercers, andnormalize_processing_config. Inpainters importbackend.configdirectly.backend/detection_geometry.pyowns the normalized OCR record. It keeps the legacy bounding box beside optional polygon vertices, recognized text, confidence, and a stable tracker ID. It clips and remaps geometry for the current frame, then rasterizes each shape with local expansion.backend/processor.pypreserves the legacy public import surface and delegatespython -m backend.processortobackend.cli.main.backend/detection.py,backend/tracking.py,backend/io.py(capture, ffprobe, and exact rational timing),backend/quality.py, andbackend/inpainters/own the focused pipeline pieces.backend/encoder.pyprobes hardware encoders and selects the output codec (H.264 / H.265 / AV1 / VVC).backend/presets.pyholds the one place a preset definition is allowed to live.backend/model_hashes.pyowns vendored weight hashes and the chunked SHA-256 verifier.backend/adapter_manifest.pyowns the immutable VACE repository and commit allowlist, required artifact hashes, directory verification, and the durable model provenance record. Verification finishes before model import.backend/model_downloads.pyowns the complete inventory of optional runtime model fetches used by first-run guidance, backend status, and support bundles.backend/execution_provenance.pycarries a loaded model's repository, commit, file hashes, cache path, and unsafe-override state into output sidecars and batch evidence.backend/language_support.pyowns the distinction between the GUI's selectable OCR language codes and broader OCR engine language capacity reported in support/backend status.
- Ingest.
gui.app.VideoSubtitleRemoverApp._on_files_dropped->_add_to_queuebuildsQueueItementries, each carrying its ownProcessingConfigsnapshot. Queue capped at 500. - Per-item dispatch.
_process_queuewalks the queue;_process_itemtranslates the GUIProcessingConfigto the backendProcessingConfigand instantiates aSubtitleRemover(or reuses a cached one when mode/device/lang match). - Backend constructor.
backend.processor.SubtitleRemover.__init__:- Normalises the config via
normalize_processing_config. - Builds the OCR
SubtitleDetector. Auto resolves a cascade, while a named engine must load without changing implementations. - Picks the inpainter (
STTNInpainter/LAMAInpainter/ProPainterInpainter/AutoInpainter). - Probes the matching HW encoder family for
output_codec. - Optional NVML free-VRAM probe scales
sttn_max_load_num.
- Normalises the config via
- Optional preprocessing.
process_video:- ffprobe
idet->ffmpeg yadifdeinterlace when auto-detected. - ffprobe keyframe enumeration when
keyframe_detection. - ffprobe timing fields are retained as integer PTS and duration ticks with
the stream's rational time base. FFmpeg 9
durationfields are primary; packet-duration names are legacy fallbacks. Missing, repeated, and non-monotonic PTS are repaired with warning records, while edit-list starts stay available for validation.
- ffprobe
- Decode.
_open_captureeither opens acv2.VideoCapture(with optionaldecode_hw_accel) or a_FrameSequenceCapturefor an image-directory input. Whenprefetch_decodeis on, the cap is wrapped in a_PrefetchReaderdaemon worker that feeds a bounded queue. Tagged PQ and HLG sources use abgr48lesurface. Untagged 8-bit YUV sources need an ffprobe-verified 8-bit surface or an explicittvorpcrange before the SDR path is accepted. OCR and model inputs receive a separate tone-mapped 8-bit proxy, while the high-bit source remains attached to the batch for final repair. If the native reader cannot provide that surface, processing stops rather than falling back to BGR8. - Per-frame detect. Inside the main loop:
- Manual region is an engine-independent branch before OCR. When
sttn_skip_detectionis true, a configured fixed, timed, or moving region is rasterized as the complete mask and passed unchanged to the selected Auto, STTN, LaMa, or ProPainter implementation. A missing region stops the run instead of silently falling back to detection. Automatic mode keeps saved fixed regions and adds them to OCR detections. pHashskip + keyframe gating short-circuit when content is unchanged.SubtitleDetector.detect_with_geometry(frame)calls the active engine (RapidOCR / PaddleOCR / Surya / EasyOCR / OpenCV) and keeps polygon vertices beside the compatibility boxes.detect(frame)remains the rectangle API for older callers._group_horizontal_geometryfuses karaoke syllables while keeping their recognized text and confidence.SubtitleTracker.update_with_geometrysmooths boxes and remaps polygon vertices with the tracked translation and scale. Text and confidence stay attached to a stable ID.updateremains the rectangle API.- SRT export consumes those tracked observations directly. A conservative grapheme-aware consensus picks cue text, while engines without recognized text use the compatibility fallback. The writer keeps exact source frame timestamps for CFR and VFR input.
categorizefilters chyron vs subtitle when eitherremove_chyrons/remove_subtitlesis off._create_maskproduces the binary mask (with dilation). Polygon records are filled and expanded independently, so one rotated caption cannot widen another caption's mask._expand_mask_by_colorextends to dominant-colour pixels._accumulate_quality_bboxwidens the union-mask bbox used by the ROI quality metric.
- Manual region is an engine-independent branch before OCR. When
- Per-batch inpaint. The current batch of
(frame, mask)pairs is passed to the inpainter chosen above:STTNInpainter:_temporal_background_exposereconstructs the true background from temporally-exposed neighbours.LAMAInpainter: the registered LaMa implementation uses ONNX Runtime, OpenCV 5 DNN, or the explicitsimple-lama-inpaintingPyTorch opt-in. If none can run, the named request fails instead of substituting cv2 pixels.ProPainterInpainter: TBE with a higher coverage bar + LaMa residual blend (MIT-licensed hybrid, not the ICCV 2023 model).AutoInpainter: per-batch routing on the exposure score; idle-LaMa is unloaded afterLAMA_IDLE_UNLOAD_AFTERTBE batches. All paths terminate inapply_finishing(edge-ring colour match then feather blend). HDR output converts only the active mask ROI to bounded linear light, lifts the proxy result with high-bit boundary detail, and reapplies the source PQ or HLG transfer function. Outside-mask pixels stay byte-identical to the decoded source surface.backend.execution_provenancerecords requested and actual implementations, providers, execution counts, and failure classes. Only Auto may cross an implementation boundary, and its ordered attempts remain in the fallback chain. Named OCR, inpaint, segmentation, tracking, and restoration stages stop with a recovery hint when load, runtime, or output validation fails.
- Intermediate write.
_LosslessIntermediateWriterpipes raw BGR frames throughffmpeg -c:v ffv1so the final encode is the only lossy step. Falls back to legacymp4vwhen ffmpeg is absent. Variable-rate frame sequences are first stream-copied into a lossless PNG-in-MOV timing carrier. Its packet durations come from adjacent integer PTS values, with the probed source duration retained for the final frame, before the requested codec sees the frames. - Mux + finalise.
_merge_audiore-encodes the FFV1 temp into the user-visible H.264 / H.265 / AV1 / VVC (H.266) output (HW encoder when available, software fallback peroutput_codec). Audio path honours:- Time-range trim.
- Multi-track passthrough (
-map 1:a?). - Per-stream loudness normalisation (
-filter_complexbranch). - Adaptive
_ffmpeg_subprocess_timeoutscaled to source duration. - Exact frame-range ticks are converted to FFmpeg boundary strings only at the tool boundary, so audio, SRT, EDL, and FCPXML share one clock.
- Quality report. When
quality_reportis on,_compute_quality_reportsamples N frames from input and output, computes both whole-frame and ROI-cropped PSNR/SSIM (the ROI is the union mask bbox), and reopens the final encoded output against persisted per-frame masks before calculating mask-local evidence. The temporal pass estimates motion from untouched pixels, excludes scene cuts, gates on the worst valid pair, and records it with a timestamp and PNG overlay. It also measures outside-mask CIELAB drift for SDR or linear-light drift for tagged HDR. Optional_write_quality_sheetrenders the side-by-side PNG. The quality gate ladder escalates through increase-dilation, temporal-smooth, alternate-inpainter, and manual-review. Color drift always remains a review signal and never triggers automatic recoloring.
backend/release_verification.py records the external FFmpeg banner,
configuration, compiler line, and configuration hash in ffmpegRuntime. It
also records OpenCV wheel provenance and the embedded avcodec, avformat,
and avutil ABI versions in opencvFfmpeg. Those ABI values are not treated
as upstream FFmpeg release tags. A release blocks only when a cited advisory
rule maps a component ABI to an affected range. The current OpenCV build has
no such mapping and is reported as unmapped without a vulnerability claim.
- Batch report.
backend/batch_report.pywritesvsr-batch-summary.jsonandvsr-batch-summary.mdwith per-item status, codec/duration data, quality gate results, remediation suggestions, failed stage identity, and recovery guidance. Completed outputs also receive a v3 sidecar with full source and output hashes, normalized processing settings, canonical output path, and byte counts. Skip-existing and completed-checkpoint decisions require every identity field to match. The legacyanypolicy is explicit and appears as unverified evidence in both report formats. - Progress, preview, cancel. During every batch:
on_progress(progress, message)ticks the GUI progress bar and Windows taskbar.on_preview_frame(frame, idx, total)marshals an inpainted frame to the Tk preview pane.cancel_event(global) and the per-itemcancel_requestedflag each raiseInterruptedErrorfrom the progress callback so the batch can stop cleanly.
[settings.json]
| load_settings + _migrate_settings (schema backfill)
v
[GUI ProcessingConfig] (single source of truth in gui/config.py)
| per QueueItem snapshot via to_dict / from_dict
v
[QueueItem.config] (immutable from this point unless re-snapshotted)
| _process_item builds the BackendConfig and passes it down
v
[backend ProcessingConfig] (backend/config.py)
| normalize_processing_config (idempotent, runs on hot-swap)
v
[runtime: SubtitleRemover.config]
- Persistence is dataclass-driven via
dataclasses.fields(self)so a new field lands in settings.json automatically. - The GUI
_sync_config_from_uiis the one place a tk variable maps to a config field; every new toggle adds ahasattrguard here. - Hot-swap of a cached remover re-runs
normalize_processing_config(backend_config)to defang any NaN/inf or out-of-range per-item override.
For a new ProcessingConfig field:
- Declare the dataclass field with a backend-default value in
both
gui/config.py:ProcessingConfigandbackend/config.py:ProcessingConfig. - Add a coercion entry to
normalize_processing_config(backend) andProcessingConfig.normalized()(GUI) with safe bounds. - Pass the field through
_process_item->BackendConfig(...). - Surface it in the GUI: add a tk variable + an Advanced card widget,
then sync it in
_sync_config_from_ui. - Surface it on the CLI: add
parser.add_argument(...)and map it in theconfig = ProcessingConfig(...)block. - Add a regression test that round-trips the field through to_dict + from_dict.
- Bump
VSR_SETTINGS_FORMATonly when the new field's semantics require a migration. A backend-default new key does not.
For a new inpainter:
- Subclass
BaseInpainterwith aninpaint(frames, masks)method. - Add the mode to
InpaintMode(both GUI and backend enums). - Add a branch to
SubtitleRemover._create_inpainter. - Add the GUI label to
InpaintModeandmode_mapin_process_item. - If the inpainter loads weights at runtime, register the
vendored SHA-256 in
backend/model_hashes.py:KNOWN_WEIGHT_HASHESand callverify_weight_filefrom the loader.
For a new OCR detector:
- Add a probe + lazy-load block in
SubtitleDetector._load_model(respect the cascade priority). - Add a
_detect_<engine>method that returns a list of(x1, y1, x2, y2)tuples. - Register the engine name in
detect_ai_engines()for the About dialog. - If GPL-licensed, gate behind
VSR_ALLOW_GPLlike Surya.
Microsoft has placed DirectML in maintenance mode (explicit README banner on github.com/microsoft/DirectML as of 2026). New ONNX Runtime GPU development for AMD/Intel targets is moving to Windows ML.
Current VSR state:
- AMD/Intel GPU inference uses
onnxruntime-directml==1.24.4(latest published, March 2026). It receives security patches but no new features. onnxruntime-windowsml1.27.1 is available on PyPI (Python 3.11-3.14) and provides automatic execution-provider selection.--audit-windows-mlprobes the Windows ML Python path.backend/device_provider.py:windowsml_status()reports whetheronnxruntime-windowsmlis installed (surfaced in the support bundle).
Migration prerequisites:
- Confirm
onnxruntime-windowsmlprovides equivalent EP selection for the OCR and inpaint ONNX models on AMD/Intel GPUs. - Benchmark latency versus the current DirectML path.
- Update
dependency_profiles/directml.txtto pinonnxruntime-windowsmlinstead ofonnxruntime-directml. - Update
setup.pyto install the new package on AMD/Intel hardware.
No urgent action is needed: DirectML continues to receive security
patches and functions correctly. Track onnxruntime-windowsml
releases and confirm inference parity before switching the default.
process_videois monolithic (~250 lines). Splitting it into detect / inpaint / mux phases is on the roadmap but every existing call site assumes the current state machine, so the split needs careful test coverage first.- The cached-remover reuse in
_process_itemsaves model-load time across batch items but means a config change that needs a different detector engine triggers a full reload (mode + device + lang form the cache key). _PrefetchReaderrequires strict ownership: once it wraps a cap, the main thread cannot touch the underlying object directly. Cleanup goes throughreader.release()so a mid-batch crash never leaks the worker thread.- The FFV1 intermediate (
_LosslessIntermediateWriter) needs ffmpeg on PATH; falls back tomp4vautomatically. The fallback reverts to v3.12 behaviour (lossy intermediate).
What is actually tested here, and what is explicitly not supported. Keep this honest: an untested claim is worse than a documented gap.
| Surface | State | Proof |
|---|---|---|
| Keyboard reachability of major actions | Supported and tested | tools/ui_scaling_probe.py asserts every major action is focusable, has non-zero geometry, and is not clipped, across the scale/theme/locale matrix; tests/test_text_scaling.py keeps the probe in active collection |
| Text scaling 100-200% | Supported and tested | Same probe at 100/125/150/175/200%; fonts, control heights, and wrap lengths must all scale |
| Dialog reflow and scrolling at high scale | Supported and tested | gui/dialog_layout.py; the probe opens the dialogs at 980x720 and 2752x1152 work areas and requires an internal scroll path |
| High-contrast theme | Supported and tested | Probe runs the whole matrix under the high-contrast palette |
| Pseudo-locale (qps-Ploc) string expansion | Supported and tested | scripts/i18n_catalogs.py; probe renders pseudo-localised strings |
| RTL mirroring | Supported and tested (pseudo-RTL) | Probe checks theme direction, label justification, and mirrored toggle geometry |
| Accessible names/roles on standard and custom widgets | Supported as an MSAA bridge | backend/a11y.py annotates names, roles, values, descriptions, and help text on native widget HWNDs; the active release probes cover metadata and focus behavior |
| Screen readers / UI Automation on custom controls | Live client proof blocked | The Canvas-based controls expose the MSAA bridge but do not implement native UIA patterns. Narrator/NVDA validation requires an isolated virtual monitor or user session. The current headless release build records the limitation instead of claiming a live reader result |
If you need screen-reader support today, the CLI (python -m backend.cli) is
the accessible surface: it is plain text, fully keyboard driven, and every
option in the GUI has a CLI equivalent.