From b3228cb4f4c094d0741e22a121fb1e98d9e750fe Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Mon, 21 Sep 2026 11:18:29 +0200 Subject: [PATCH] feat(downloads): estimate a transcode's size so the progress bar moves MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A transcode is produced as it is sent — chunked, with no Content-Length — and the worker reported progress 0.0 for its whole duration: an empty bar reading "0%" while the byte count climbed for an hour. That is the case every film whose audio must be re-encoded lands in. The backend already fetches the item to decide the audio policy, and that item carries what a prediction needs: the source's size (an `original` download copies the picture, so the output is the source give or take the audio track) and its runtime (a preset re-encodes at fixed rates, so the size is rate × runtime — from a preset table the URL builder now shares, so the two cannot drift). The prediction is made where the URL is resolved and persisted as the row's file_size. The worker uses it only when the response has no length; the server's figure always wins; an estimated bar is capped at 99% so a low prediction never shows a finished download still running; and the Completed event now carries the bytes actually written so the frontend stops persisting the row's file_size as the final size. The row renders three honest states: exact "42%", estimated "~42%" with "X / ~Y", or — with no total at all — an indeterminate band and the bytes so far, never "0%". The single-video button joins the series/season buttons on the enqueue path so all three resolve, and predict, in one place. DR-290, UT-252, UT-253, UT-254. Co-Authored-By: Claude Opus 5 (1M context) --- docs/requirements.md | 6 +- src-tauri/src/commands/catalog.rs | 115 +++++++++-- src-tauri/src/commands/download/mod.rs | 51 +++-- src-tauri/src/download/estimate.rs | 181 ++++++++++++++++++ src-tauri/src/download/events.rs | 10 + src-tauri/src/download/mod.rs | 2 + src-tauri/src/download/presets.rs | 66 +++++++ src-tauri/src/repository/mod.rs | 78 ++++++-- src-tauri/src/repository/online.rs | 28 +-- .../components/downloads/DownloadItem.svelte | 55 ++++-- .../downloads/downloadProgress.test.ts | 61 ++++++ .../components/downloads/downloadProgress.ts | 64 +++++++ .../library/VideoDownloadButton.svelte | 15 +- src/lib/stores/downloads.test.ts | 73 +++++++ src/lib/stores/downloads.ts | 16 +- 15 files changed, 716 insertions(+), 105 deletions(-) create mode 100644 src-tauri/src/download/estimate.rs create mode 100644 src-tauri/src/download/presets.rs create mode 100644 src/lib/components/downloads/downloadProgress.test.ts create mode 100644 src/lib/components/downloads/downloadProgress.ts diff --git a/docs/requirements.md b/docs/requirements.md index 1088040db..7c048bce1 100644 --- a/docs/requirements.md +++ b/docs/requirements.md @@ -491,6 +491,7 @@ Internal architecture, components, and application logic. | DR-287 | Authentication uses only the spellings Jellyfin 12.0 leaves enabled. 12.0 disables `X-Emby-Authorization`, `X-Emby-Token`, `X-MediaBrowser-Token`, the `Emby` scheme and the `api_key` **query parameter** by default, and a migration (`DisableLegacyAuthorization`) turns them off on upgraded servers too — so a client using them stops working against an upgraded server rather than degrading. This is not a version branch: `Authorization` with the `MediaBrowser` scheme, and `ApiKey` as a query parameter, are ungated on *both* generations, and the header value this app already built was always the correct one. So the fix is a rename at 21 header sites and 28 query sites, not a capability flag. The query-parameter spelling is load-bearing rather than cosmetic: stream URLs are handed to mpv, ExoPlayer and the webview's `