From d8f08361657dfbe04631953a8c92e6a505a180c2 Mon Sep 17 00:00:00 2001 From: xRangerDE Date: Sat, 21 Mar 2026 15:47:19 +0100 Subject: [PATCH] fix: ETA calculation was using video duration instead of download progress The old formula (avgSpeed * expectedDurationSeconds) simplified to just (videoDuration - elapsedTime), showing 59min ETA for a 60min part after 1min of downloading. Now uses streamlink's actual progress percentage: ETA = (elapsed / percent) * (100 - percent), which reflects real download speed rather than video length. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/main.ts | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/main.ts b/src/main.ts index 9c66833..aa59191 100644 --- a/src/main.ts +++ b/src/main.ts @@ -2203,6 +2203,7 @@ function downloadVODPart( const args = [...streamlinkCmd.prefixArgs, url, 'best', '-o', filename, '--force']; let lastErrorLine = ''; const expectedDurationSeconds = parseClockDurationSeconds(endTime); + let lastStreamlinkPercent = 0; if (startTime) { args.push('--hls-start-offset', startTime); @@ -2250,19 +2251,13 @@ function downloadVODPart( lastTime = now; let etaStr = ''; - if (speed > 0 && downloadedBytes > 0) { - const itemStartTime = itemTracking.startTime; - const elapsedSec = (Date.now() - itemStartTime) / 1000; - if (elapsedSec > 5) { // Wait at least 5 seconds before showing ETA - const avgSpeed = downloadedBytes / elapsedSec; - if (expectedDurationSeconds && expectedDurationSeconds > 0) { - const estimatedTotalBytes = avgSpeed * expectedDurationSeconds; - if (estimatedTotalBytes > downloadedBytes) { - const remainingSec = (estimatedTotalBytes - downloadedBytes) / avgSpeed; - if (remainingSec > 0 && remainingSec < 86400) { // Between 0 and 24 hours - etaStr = formatETA(remainingSec); - } - } + if (downloadedBytes > 0) { + const elapsedSec = (Date.now() - (itemTracking?.startTime || Date.now())) / 1000; + if (elapsedSec > 5 && lastStreamlinkPercent > 1) { + // Use streamlink's reported progress for accurate ETA + const remainingSec = (elapsedSec / lastStreamlinkPercent) * (100 - lastStreamlinkPercent); + if (remainingSec > 0 && remainingSec < 86400) { + etaStr = formatETA(remainingSec); } } } @@ -2290,6 +2285,7 @@ function downloadVODPart( const match = line.match(/(\d+\.\d+)%/); if (match) { const percent = parseFloat(match[1]); + lastStreamlinkPercent = percent; onProgress({ id: itemId, progress: percent,