8000 GitHub - inket/archivelo: A vibe-coded cycling video archiver · GitHub
[go: up one dir, main page]

Skip to content
inketPublic

About

A vibe-coded cycling video archiver

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Archivelo

A small, self-hosted archiver for cycling race videos. It browses a source site's uploads, lets you subscribe to specific races/categories, and automatically downloads new videos as they're published — via yt-dlp — into a folder structure on disk you control.

Runs as a single Docker container with a small FastAPI + HTMX web UI for tracking discovery and download status.

Archivelo's Latest Uploads page

Features

  • Latest Uploads feed and a Races & Categories browser, both scraped live from the source site
  • Subscribe to a category to auto-download new uploads going forward — browsing never triggers a download on its own, only subscribing or an explicit click does
  • Resumable downloads — a stuck/stalled download is detected and killed automatically (independent OS-level watchdog, not just yt-dlp's own timeout) and retried with exponential backoff
  • Cancel / Resume / Delete for an in-progress download, and Redownload for anything already saved
  • Stream from source for videos that aren't downloaded yet — plays straight from the source site's CDN (or its YouTube embed) without saving anything, and remembers the playback position just like a downloaded file
  • Theater mode on the video page — a bigger player and less surrounding clutter, without going into browser fullscreen
  • Push notifications (via Pushover) when a download starts, finishes, or gives up after exhausting its retries, linking straight back to the video
  • Archive view of everything downloaded, with both download and upload dates
  • Runtime-configurable Settings page (poll interval, retry limits, concurrency, source host, notifications) — no restart needed
  • Survives container restarts cleanly: an interrupted download is requeued automatically on startup instead of silently stalling forever

Quick start (Docker Compose)

curl -O https://raw.githubusercontent.com/inket/archivelo/main/docker-compose.yml
docker compose pull
docker compose up -d

The app will be available at http://<host>:8000. Two volumes get created next to docker-compose.yml: ./config (database + log — small, worth backing up) and ./downloads (the actual video files — large, point it at a different drive/mount if you want by changing the host-side path in docker-compose.yml).

To update later: docker compose pull && docker compose up -d. docker-compose.yml pulls the latest tag, which always points at the most recently published release — not every commit. Pin image: to a specific version instead (e.g. ghcr.io/inket/archivelo:0.1.0) if you'd rather control updates manually.

Configuration

All of these are set as environment: entries in docker-compose.yml:

Variable Default Purpose
SOURCE_BASE_URL (the source site) Host to scrape, in case it ever moves
POLL_INTERVAL_SECONDS 900 How often subscribed categories are checked for new uploads
RETRY_INTERVAL_SECONDS 300 How often a failed discovery check is retried
MAX_RETRIES 5 Auto-retry attempts for a failed download before giving up
MAX_CONCURRENT_DOWNLOADS 1 How many downloads run at once
DISCOVERY_PAGE_DEPTH 3 How many listing pages deep to check per category
PUID / PGID 0 / 0 (root) Set to your host user's uid/gid so files under ./config and ./downloads aren't owned by root
BASE_PATH (empty) Set if serving behind a reverse proxy at a subpath, e.g. /archivelo for https://example.org/archivelo — see below

Most of these (poll interval, retry limits, concurrency, source host) can also be changed later from the Settings page in the UI without restarting the container — the env var only supplies the initial value.

Serving at a subpath

If you're putting Archivelo behind a reverse proxy at https://example.org/archivelo rather than its own domain/subdomain, set BASE_PATH=/archivelo. The app owns that prefix internally (the same "URL Base" pattern apps like Sonarr/Radarr use) — a plain forward is enough, no rewrite/strip rule needed on the proxy side:

location /archivelo/ {
    proxy_pass http://archivelo:8000;
}

If you're using a subdomain instead (https://archivelo.example.org), leave BASE_PATH empty — no path rewriting is involved.

Local development

Requires Python 3.12+ and ffmpeg on PATH, plus deno for YouTube-hosted videos (yt-dlp uses it to solve YouTube's player challenges).

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt

cp .env.local.example .env.local   # or create your own; see app/config.py for all variables
set -a && source .env.local && set +a
.venv/bin/uvicorn app.main:app --reload

How it works

  • Discovery and downloads run as background threads inside the same process — no separate worker/queue service.
  • The site's markup is scraped with a mix of BeautifulSoup and targeted regexes (some of its HTML is malformed enough that a strict tree parse misses content).
  • Downloads shell out to yt-dlp as a subprocess rather than using its Python API, with an independent watchdog thread that kills and retries a download if it stalls — this proved more reliable than relying on yt-dlp's own internal timeouts.
  • yt-dlp upgrades itself (pip install -U) right before each download, since YouTube changes often enough to break older versions. In the Docker image it lives in its own venv (/opt/yt-dlp) so the upgrade never touches the app's dependencies; if the upgrade fails, the download proceeds on the installed version.
  • Publishing an image to ghcr.io/inket/archivelo is decoupled from pushing to main — see Releasing below. Deploying is just pulling; nothing gets built on the host.

Releasing

Images are built by .github/workflows/docker-publish.yml, triggered only when a GitHub Release is published — plain pushes to main don't build or publish anything. Versions follow semver; while the project's still early, that means 0.MINOR.PATCH (bump MINOR for features, PATCH for fixes), moving to 1.0.0 once it feels stable.

To cut a release:

git tag v0.1.0
git push origin v0.1.0
gh release create v0.1.0 --generate-notes

That publishes ghcr.io/inket/archivelo:0.1.0 and moves the latest tag to it.

License

MIT — see LICENSE.

About

A vibe-coded cycling video archiver

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0