You are a Rust engineer who ships production CLI + small localhost web-server applications on Windows. Recommend a concrete stack with exact crate versions. Be opinionated; name when a popular crate is the wrong choice, and give a runner-up for each decision.
subtitle-rust — a Rust tool that synchronizes subtitle files. Given a reference subtitle and a target subtitle of the same film, it recovers the timing error in the target and rewrites only its timestamps. It never alters cue text.
A predecessor C++ tool (subsync, ~9,000 lines C++17, zero third-party dependencies) attempted this and does not reliably work on real files. I am not porting it — this is a fresh design that may borrow good ideas. Maintainability and correctness are the point.
- Subtitle formats: SRT, ASS/SSA, WebVTT, MicroDVD. Write-back must preserve cue text and markup byte-exactly — only the time token changes; an unmodified file must round-trip losslessly. Charset handling matters: UTF-8, UTF-8 BOM, CP1252, Shift-JIS (the C++ version had a charset module).
- CLI: align,
--dry-run,--json,--output,--undo(restore backup),--quiet,--version,--formats, confidence threshold, encoding override. - Embeddings via ONNX:
intfloat/multilingual-e5-smallint8 (~118 MB), throughort. Tokenizer must load the model's XLM-RoBERTa SentencePiecetokenizer.json(vocab 250,002). Inputs int64; masked mean pooling; L2 normalization; batch inference, ~3,000 cue lines per film. - Local web UI:
--uistarts a localhost-only server serving a single-page app — drag-drop two files, see the detected shift and a preview, confirm or cancel. The C++ version had a loopback server with a token-gated JSON API; the new one should be better. - Windows distribution: ideally one
.exe, no install, including the ONNX runtime and model (or a documented side-by-side layout). - Performance: Intel Core i3-N305 (8 efficiency cores, AVX2 + AVX-VNNI, no AVX-512), 8 GB RAM, CPU-only. Under ~1 GB RAM during inference; a film in seconds.
The C++ tree had modules: subtitle (parsers), charset, format_{srt,ass,sub,vtt}, correlate, drift, align, fft, vad, wav, textembed/textfeat/textalign/tokbpe/onnxenc, ui, timing, engine, main; a vendored third_party/onnxruntime loaded via LoadLibraryW at runtime (so the build had no import library); a models/bekko.onnx; and tests split between C++ unit tests and Python harnesses (bench.py, eval_text.py, stress.py). The audio path (fft/vad/wav) is out of scope for the rewrite. The onnxenc path was left disabled by default, which is a large part of why cross-language sync was weak.
A. ONNX runtime. Confirm ort or argue otherwise. Compare ort, tract (pure Rust), candle, and a Python-subprocess fallback in this exact table:
| Runtime | Version | Needs separate onnxruntime DLL? | int8 quantized support | AVX2 (no AVX-512) CPU perf | Windows packaging | Binary size impact | Maturity | Verdict |
|---|---|---|---|---|---|---|---|---|
| ort | ||||||||
| tract | ||||||||
| candle | ||||||||
| python subprocess |
Flag the N305-specific trap: it has AVX-VNNI but not AVX-512, and int8 exports come as qint8 (signed) vs quint8 (unsigned) — explain the saturation/dispatch risk and give the exact way to verify the quantized model matches fp32 output.
B. Tokenizer. Which crate and version; pitfalls loading a 250,002-vocab XLM-RoBERTa tokenizer.json and truncating at 64 tokens.
C. Subtitle parsing. For each of SRT/ASS/VTT/MicroDVD, recommend a crate or "hand-roll", and justify with the byte-exact round-trip requirement. Most crates re-render and lose formatting — call out which do.
D. CLI. clap version + derive vs alternatives. Give the argument structure for the commands in requirement 2, including a clean --undo/backup design.
E. Web UI. For a localhost-only server with a few JSON endpoints and file upload, compare axum, actix-web, tiny_http, warp in this table:
| Framework | Version | Compile time | Binary size | Right weight for a localhost tool? | Why not |
|---|---|---|---|---|---|
| axum | |||||
| actix-web | |||||
| tiny_http | |||||
| warp |
Also: embedding the static frontend (include_dir vs rust-embed), and the browser-security footguns of a local server (CSRF, binding to 127.0.0.1, tokens).
F. Numerics. ndarray vs nalgebra vs plain slices for ~1500×1500 f32 matrices and DP. Pick the lightest pleasant option, and say whether to use a DTW/alignment crate or hand-roll the DP.
G. Errors, logging, config. anyhow + thiserror versions; tracing vs log; where config lives; and the mechanism for secrets (subtitle API keys) — env var or untracked local config, never hardcoded.
H. Packaging. The Windows single-exe recipe: +crt-static, bundling the ONNX runtime DLL, model + tokenizer as embedded assets vs side-by-side, release profile (lto, codegen-units, panic=abort), and a realistic resulting binary size.
I. Testing. Unit tests, fixture-based integration tests, and a harness for an external real-subtitle corpus (on disk, not committed). Recommend the shape (cargo test vs a separate binary vs criterion for benches).
Cargo.toml— every dependency with version, features, and a one-line why.- Answers A–I — each as a pick + runner-up, using the tables above where given.
- Windows single-exe recipe — exact flags and final file layout.
- Minimal
main.rsskeleton wiring CLI → engine → web UI dispatch. - Risk table —
| Dependency | Risk | Fallback |. - What I should decide differently — if a requirement is a mistake, say so.
Prioritize correctness, lossless round-trip, small binary, low RAM, maintainability. Prefer mature crates. If a version number is uncertain, say so rather than guessing.