Skip to content

Continue paused and interrupted downloads where they stopped - #24

Merged
combor merged 2 commits into
mainfrom
resume-downloads
Oct 1, 2026
Merged

combor merged 2 commits into
mainfrom
resume-downloads

Conversation

@combor

@combor combor commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Pausing a download, restarting magnetowid or retrying a failed attempt used to start the download over. magnetowid now fetches HLS segments itself, four at a time, into .incomplete/<job id>, and ffmpeg only remuxes the saved files into the MP4 (same language tag and +faststart as before). A resumed download looks the stream up again, since its URLs expire, and skips the segments already saved.

  • Which saved files are reused. Segments are saved by position, because their URLs carry tokens that change with every lookup. The local playlists record the rendition, its bandwidth, every segment's duration and a hash of the file names. If the site serves a different stream, the saved files are discarded and the download starts over.
  • Failed segments. Server errors, rate limits, stalls and error pages served as segments are retried up to five times per segment. Other client errors, such as an expired token, fail the attempt; the queue's retry then resolves fresh URLs and continues.
  • Damaged files. If ffmpeg reports a saved file damaged or unreadable, the segments are discarded. Other remux failures, such as a full disk, keep them.
  • Queue. A job's folder is kept through pauses, restarts and retries, and removed when the job finishes, fails for good or is removed. Paused jobs keep their progress ("Paused at 40%"), and the time left counts only the current attempt.
  • Fallback. Live, encrypted and non-HLS streams still go straight to ffmpeg and start over.
  • Docs and UI. The "restarts from the beginning" copy is gone. The docs note that finishing needs free space for about twice the video's size.

Testing

  • make test and make integration pass.
  • Remuxing local playlists works with ffmpeg 6.1 (Ubuntu 24.04), 8.1 (Alpine 3.24) and n9, for fMP4 with separate audio and for TS.
  • Against BBC and TVP: a download was stopped after 12 files, the programme looked up again, and the download continued without fetching any saved file again. Segment names, durations and bandwidth stayed the same across lookups. TVP's URL paths change with every lookup, which is why the fingerprint uses file names rather than paths.
  • New tests cover:
    • resuming, and starting over for a changed stream
    • segment retries, stalls and error pages
    • bounded parallelism
    • damaged and unreadable files, and output failures
    • the ffmpeg fallback
    • the queue keeping or removing the work folder

combor added 2 commits October 1, 2026 10:30
LoadMedia lists a VOD media playlist's segments with their durations,
initialization sections and discontinuities, resolving URIs against the
playlist's URL after redirects. Playlists whose segments can't simply be
fetched one by one return ErrUnsupported: live and encrypted ones, and
those with byte ranges, gaps or variables. Neither BBC nor TVP uses
these.

Playlists may now be up to 16 MiB, as hours of short segments with
tokenized URIs exceed the old 1 MiB, and longer ones fail instead of
being cut short.
Pausing a download, restarting magnetowid or retrying a failed attempt
started the download over: ffmpeg wrote the MP4 in one pass, and the
queue deleted the partial file. magnetowid now fetches HLS segments
itself, four at a time, into the job's folder in .incomplete, and ffmpeg
only remuxes the saved files. A resumed download looks the stream up
again, since its URLs expire, and skips the segments already saved. A
segment appears under its final name only once it is complete.

Segments are saved by position, because their URLs carry tokens that
change with every lookup. The local playlists ffmpeg reads name the
rendition, its bandwidth and a hash of the segments' file names, so if
the site serves a different stream, the saved segments are discarded
and the download starts over.

A segment that fails with a server error, a rate limit, a stall or an
error page is fetched up to five times. Other client errors, such as an
expired token, fail the attempt, and the queue's retry resolves fresh
URLs and continues. If ffmpeg finds a saved file damaged or unreadable,
the segments are discarded so that retries fetch them again; other
remux failures, such as a full disk, keep them.

The queue keeps a job's folder through pauses, restarts and retries,
and removes it when the job finishes, fails for good or is removed.
Paused jobs keep their progress, shown as "Paused at 40%", and the time
left counts only the current attempt's progress. Live, encrypted and
non-HLS streams still go straight to ffmpeg and start over.

Finishing a download needs free space for about twice the video's size.
@combor
combor merged commit bdb5e4d into main Oct 1, 2026
7 checks passed
@combor
combor deleted the resume-downloads branch October 1, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant