feat(downloads): estimate a transcode's size so the progress bar moves
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) <noreply@anthropic.com>
This commit is contained in:
@@ -64,14 +64,10 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const repo = auth.getRepository();
|
||||
const handle = auth.getRepository().getHandle();
|
||||
|
||||
log.debug("🎬 Starting video download for item:", itemId, "quality:", quality);
|
||||
|
||||
// Get stream URL based on quality
|
||||
const streamUrl = await repo.getVideoDownloadUrl(itemId, quality);
|
||||
log.debug(" Stream URL obtained");
|
||||
|
||||
// Get target directory
|
||||
const targetDir = await commands.storageGetPath();
|
||||
|
||||
@@ -109,9 +105,12 @@
|
||||
// Pin the item metadata
|
||||
await downloads.pinItem(itemId);
|
||||
|
||||
// Actually start the download
|
||||
await commands.startDownload(downloadId, streamUrl, targetDir);
|
||||
log.debug(" Download started");
|
||||
// Resolve the URL and start it the same way the series/season buttons
|
||||
// do: Rust picks the transcode from the row's preset, predicts the size
|
||||
// so the bar has a total when the response has no length (DR-290), and
|
||||
// the queue pump starts it when a slot is free.
|
||||
await commands.enqueueVideoDownloads(handle, [downloadId], targetDir);
|
||||
log.debug(" Download enqueued");
|
||||
} catch (error) {
|
||||
log.error("Failed to start video download:", error);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user