Better model download management

This commit is contained in:
Lucas Winther
2026-07-14 20:35:03 +02:00
parent 42fe27d2dd
commit 8464f0e492
6 changed files with 86 additions and 7 deletions
+5 -2
View File
@@ -107,8 +107,11 @@ are the remaining M5 work; see `WorkBreakdown.md`.)
### 4.1 Browser transcription (anonymous, default)
1. User picks a model in `ModelPicker` (curated catalog from `lib/models.ts`, with
size estimates and a Cache-API-backed "downloaded" badge); UI posts
`{type:"load", modelId, device}` where `device` is a preference
size estimates and a Cache-API-backed "downloaded" badge). Selection alone
downloads nothing (D-020): the UI posts `{type:"load", modelId, device}` when a
browser-engine transcription starts (file drop / live start) or when the user
clicks the explicit **Download** button on the selected model; server-engine
runs never post a load. `device` is a preference
(`"auto" | "webnn" | "webgpu" | "wasm"`, default `"auto"`). An explicit `dtype`
override is expressible in the message but normally omitted.
2. Worker resolves the device (D-004, D-017): for `"auto"` it probes
+18
View File
@@ -272,3 +272,21 @@ and its loaded pipeline are left untouched in that path.
**Why:** M7 future want. Enables logged-in users on weak devices to transcribe live microphone audio using the server engine.
**Shape:** The client opens a WebSocket connection to `/api/transcribe/live`. The client streams 16kHz Float32 PCM chunks (from `MicCapture`) over the WebSocket. The server runs `LiveTranscriber` and `LiveSegmenter` (from `src/lib/live.ts`, which is pure and runs perfectly in Node/Bun). For each segment/pass, the server's `LiveTranscriber` writes the audio to a temporary file and invokes the Python sidecar. The server sends `LiveUpdate` objects back to the client over the WebSocket.
**Consequence:** The client does zero ML and minimal buffering, acting only as a mic-streamer and UI-renderer for live passes on the server.
## D-020 — Model downloads are user-initiated, never a side effect of selection
**Status:** Accepted (2026-07-14)
Selecting a model in `ModelPicker` (or changing the backend preference) no longer
starts the weight download. Weights load exactly when they are needed or asked for:
- **Lazy:** a file drop or live start on the **browser** engine posts the
(idempotent) load, as both paths already did — the download overlaps decoding /
mic startup.
- **Explicit:** a **Download** button on the selected, not-yet-cached model in
`ModelPicker` starts the load immediately — this keeps D-005's "prepare for
offline use" story alive now that selection alone caches nothing.
- **Server engine:** server runs never touch the browser pipeline, so with the
toggle on "server" nothing downloads. (Previously the eager selection load
downloaded browser weights even when every transcription would run server-side.)
**Consequence:** model/backend switches just reset the load UI state
(`loadStarted`, progress); the next load starts from clean progress. The explicit
download is a full pipeline load, so it also warms up inference and surfaces the
"Running on …" backend badge.
+5
View File
@@ -242,6 +242,11 @@ Notes (M5):
models, versioned/cleaned by the SW itself) is deliberately not
surfaced — deleting it per-model makes no sense and the SW would
just re-fetch it.
- [x] Model downloads are user-initiated (D-020): selecting a model/backend no
longer auto-downloads weights; the load starts on browser-engine
transcription start (file drop / live start) or via an explicit
per-model Download button in `ModelPicker` — and never when the engine
toggle is set to "server".
- [ ] Basic a11y pass (keyboard, focus, aria on progress/live transcript)
- [ ] Production build + `bun start` deployment check; README for deployers