Offline downloads
Offline downloads let you save a movie, episode, track, or audiobook in the Gallery mobile app and play it without a network. The server converts the file to H.265 first, so the download is small. The server keeps the converted file until the app collects it.
For users#
How a download works#
- Choose a quality and start the download in the app.
- The server converts the file. The app shows Waiting for server while the conversion queues or runs.
- When the file is ready, the app downloads it. It shows Ready on server, will download automatically until the transfer starts.
- The app checks the size of the saved file and tells the server. The server then deletes its copy after 10 minutes.
You do not need to keep the app open. The server owns the conversion. Close the app, lock the phone, or restart it. When you open the app again, it asks the server for the state of each download and carries on. A conversion that took hours is not repeated.
What can still happen#
- The server keeps a finished file for 7 days by default. If you do not open the app within that time, the app shows Expired, restarting and starts the conversion again. An admin can change the time.
- The disk can fill up. If the server has a disk cap (see below), it deletes the oldest finished files first. The app then restarts the conversion.
- An admin can remove a download. The app shows “The server removed this download” and starts it again.
- The server can restart. A conversion that was running starts again from the beginning, with the same download. A finished file stays.
- A killed app restarts the file transfer from the start. The conversion does not run again.
Settings#
In the app, open Downloads → Settings.
- Wi-Fi only. The automatic download waits for Wi-Fi.
- Auto-download when ready. On by default. Turn it off to start each transfer by hand.
Limits#
- iOS keeps a file transfer going in the background. The conversion status is checked only when the app is in the foreground. Android has no background transfer.
- Switching accounts stops the local transfers. The server keeps the jobs. Switch back and the app carries on.
- Downloads are for the mobile app. The web app and the TV app have no offline downloads.
For admins#
Settings#
In Admin → Config → Transcode:
| Setting | Default | What it does |
|---|---|---|
| Offline Download Retention (minutes) | 10080 (7 days) | How long a finished file waits for the app. From 60 (1 hour) to 43200 (30 days). Opening the app or reading the status does not extend the time. |
| Offline Max Concurrent Transcodes | 2 | How many conversions run at once. Other downloads wait in a queue, first in first out. The minimum is 1. |
| Offline Disk Cap (MB) | 0 (unlimited) | The disk that finished files may use. |
A finished file is also deleted 10 minutes after the app confirms the download. This time is fixed. Apps that never confirm (older versions) fall back to the retention time. A failed job stays for 24 hours so the app can read the error message.
Where the files are#
Files live in <Data.BasePath>/offline-transcodes/<job id>/. Jobs are stored in the database, so they survive a restart. At startup the server:
- deletes directories that have no job,
- marks finished jobs whose file is missing as expired,
- queues conversions that were running. ffmpeg cannot resume, so each one starts from the beginning.
Disk cap and eviction#
When finished files use more than the cap, the server deletes files until the total fits:
- Files the app already confirmed.
- Then the files with the earliest deletion time.
The app is told that the job was evicted and starts it again. While the finished files fill the cap, queued conversions wait. They do not fail. The server checks the cap every 30 seconds and whenever a conversion ends. A single file larger than the cap is deleted as soon as it is ready, so set the cap above your largest expected file.
Admin page#
Admin → Transcoders lists offline jobs with the streaming transcoders. For offline jobs it shows:
- The disk that finished files use, against the cap.
- The owner, the file size, and the deletion time of each finished job.
- Whether the app confirmed the download.
Actions on a finished job (needs the transcoder management permission):
- Extend 24h adds 24 hours to the deletion time. Use it when a user is away.
- Purge Download deletes the file now. The app shows that an admin removed it, then restarts the download.
Stop on a running or queued job cancels it.
API#
| Endpoint | Purpose |
|---|---|
POST /api/transcoder/offline/start |
Start a job. A repeat request with the same clientRequestId returns the existing job. |
GET /api/transcoder/offline/jobs |
List the jobs of the signed-in user. |
GET /api/transcoder/offline/status |
State of one job. Returns 410 Gone with a reason (expired, evicted, server_restarted) when the job was removed. |
GET /api/transcoder/offline/download/{job_id} |
Download the file. Supports range requests. |
POST /api/transcoder/offline/{job_id}/ack |
Confirm the full download. The size must match. |
POST /api/transcoders/offline/{job_id}/extend |
Admin: add hours to the deletion time. |
The design and the reasons are in plans/offline-download-robustness.md.