⎇
cmd
internal
web
.dockerignore225 B
.gitignore575 B
assets.go643 B
compose.yml1.0 KB
Containerfile1.0 KB
go.mod659 B
go.sum4.8 KB
README.md3.4 KB
READMERaw

VidArchive

A self-hosted web front end for yt-dlp. It queues downloads, keeps the results in a browsable library with playback, metadata, subtitles and comments, and re-runs saved subscriptions on a schedule.

Go standard library plus chi, SQLite (pure-Go driver), and server-rendered templates. No JavaScript, no build step for the front end.

Requirements

  • yt-dlp on PATH (or set VIDARCHIVE_YTDLP_PATH)
  • ffmpeg and ffprobe for thumbnails, subtitle conversion, and media probing
  • Go 1.26+ to build from source

Missing tools are reported at startup and on /healthz; the app still starts.

Run

With the container image:

docker compose up -d          # or: podman-compose up -d

The compose file mounts ./data and publishes port 8080. The image installs yt-dlp at build time, so rebuild to update it:

docker compose build --pull --no-cache vidarchive

From source:

go build -o vidarchive ./cmd/vidarchive
./vidarchive

Then open http://localhost:8080.

Configuration

All configuration is environment variables. Templates and static assets are embedded in the binary.

Variable Default Purpose
VIDARCHIVE_PORT 8080 Listen port
VIDARCHIVE_DATA_DIR ./data Root for everything below
VIDARCHIVE_DB_PATH <data>/vidarchive.db SQLite database
VIDARCHIVE_LIBRARY_DIR <data>/library Imported media
VIDARCHIVE_TEMP_DIR <data>/temp Download scratch space
VIDARCHIVE_YTDLP_PATH yt-dlp yt-dlp binary
VIDARCHIVE_FFMPEG_PATH ffmpeg ffmpeg binary
VIDARCHIVE_FFPROBE_PATH ffprobe ffprobe binary
VIDARCHIVE_WORKERS 2 Concurrent downloads (minimum 1)
VIDARCHIVE_SCHEDULER_INTERVAL 60 Seconds between subscription checks
VIDARCHIVE_BASE_URL — External URL; an https:// value enables HSTS

Concepts

Presets collect the yt-dlp options for a download: format selection, audio extraction, subtitle and thumbnail embedding, info-JSON and comment collection, plus free-form custom flags. One preset can be the default. A download may override the format and add its own flags.

Queue. A download row is claimed by a worker, which runs yt-dlp into a scratch directory and then imports each finished item into the library. Live output is streamed into memory and flushed to the row periodically, so the detail page shows progress. Stopping the server leaves in-flight downloads downloading; they are re-queued on the next start.

Library items are directories holding one or more media files, a .vidarchive-item.toml marker, yt-dlp's info.json, thumbnails, and an optional subtitles/ directory. The marker is the source of truth for the item's name, source URL, video id, and per-file durations, so listing pages never have to run ffprobe. Directories without a marker are shown as folders, which makes the library browsable as a tree.

Subscriptions re-download a URL on a cron schedule into a directory they own. Three refresh modes:

  • overwrite — replace the existing copy of each item in place
  • skip — keep a yt-dlp download archive and fetch only new entries
  • metadata — refresh metadata for known items, download only genuinely new ones

With prune removed enabled, items no longer present upstream are deleted locally. Pruning is skipped when the source cannot be enumerated, so a network error cannot empty the directory.