👀🐶 Video Server
Find a file
JMARyA 96468086e6
Some checks failed
ci/woodpecker/push/build Pipeline failed
improve recommendation engine with scored ranking
Replace directory-only lookup with a scored query:
  +3 same channel, +2×N shared tags, +1 same directory,
  RANDOM() tiebreaker for variety. Returns up to 20 results
across the whole library so there's always something related.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:23:33 +01:00
.woodpecker no arm 2025-10-19 13:04:36 +02:00
docs refactor media model 2026-02-25 15:28:03 +01:00
migrations refactor media model 2026-02-25 15:28:03 +01:00
src improve recommendation engine with scored ranking 2026-02-25 18:23:33 +01:00
.dockerignore update 2024-12-14 23:33:47 +01:00
.gitignore refactor media model 2026-02-25 15:28:03 +01:00
Cargo.lock refactor 2025-10-19 11:49:50 +02:00
Cargo.toml refactor 2025-10-19 11:49:50 +02:00
config.toml ogp 2025-02-23 23:39:25 +01:00
devenv.lock refactor media model 2026-02-25 15:28:03 +01:00
devenv.nix refactor media model 2026-02-25 15:28:03 +01:00
docker-compose.yml ♻️ refactor 2025-02-09 07:09:20 +01:00
Dockerfile fix 2025-10-19 13:07:54 +02:00
README.md refactor media model 2026-02-25 15:28:03 +01:00
renovate.json Add renovate.json 2025-06-21 21:49:07 +00:00

WatchDogs

A self-hosted media server for organizing and serving local videos, images, and galleries. Exposes a JSON API designed to power custom frontends — a YouTube-style video browser, a TikTok-style image feed, a gallery viewer, and more.

Resource Kinds

WatchDogs manages three types of media:

  • Videos.mp4, .mkv, .webm files with metadata, thumbnails, and streaming
  • Images — Individual image files served via the API
  • Galleries — Named collections of images, browsable as a set

Features

  • yt-dlp metadata — Extracts and stores metadata produced by yt-dlp (title, description, uploader, views, tags, upload date, channel)
  • Full-text search — PostgreSQL-backed search using websearch syntax and trigram similarity for fuzzy matching
  • Thumbnails — Auto-generates thumbnails via FFmpeg; also supports custom sidecar images (.jpg, .jpeg, .png, .avif)
  • Watch history — Per-user watch history tracking
  • Multi-user auth — Session-based authentication with Admin and Regular roles, bcrypt password hashing, and CSRF protection
  • Private mode — Optionally require login to access all content
  • Open Graph Protocol — OGP metadata for video and thumbnail sharing
  • JSON API — Machine-readable endpoints for building any kind of frontend on top

Configuration

Edit config.toml before starting:

[general]
private    = true                   # Require login to access content
allow_ogp  = true                   # Serve thumbnails publicly even if private (for OG embeds)
root_url   = "http://127.0.0.1:8080"
video_path = "./videos"             # Path to your media directory

Environment variables (Docker):

Variable Description
DATABASE_URL PostgreSQL connection string
RUST_LOG Log level (default: info)
ROCKET_ADDRESS Bind address (default: 0.0.0.0)

API Routes

All /api/* routes require an API token (APIUser auth via the based framework).

Videos

Route Description
GET /api/videos?limit=N&offset=N Paginated list of videos, newest first
GET /api/videos/<id> Single video with full metadata

Images

Route Description
GET /api/images?limit=N&offset=N Paginated list of images, newest first
GET /api/images/<id> Single image metadata

Galleries

Route Description
GET /api/galleries All galleries
GET /api/galleries/<id> Gallery with its full image list

Tags & Channels (yt-dlp)

Route Description
GET /api/tags All distinct tags
GET /api/tags/<tag> Media with a specific tag
GET /api/channels All distinct channels with metadata
GET /api/channels/<id> Media from a channel

Search & Generic

Route Description
GET /api/search?query=X&limit=N&offset=N Full-text + trigram search across all media
GET /api/media/<id> Any media by ID (video or image)

Web UI

Route Description
GET / Home — random videos, latest, galleries, directories
GET /latest?offset=N Paginated recent videos (infinite scroll)
GET /latest.json JSON: recent videos (no auth)
GET /search?query=X&offset=N Search results
GET /d/<directory> Videos in a directory
GET /d/<directory>.json JSON: directory videos (no auth)
GET /galleries All galleries grid
GET /gallery/<id>?offset=N Gallery image grid (infinite scroll)
GET /image?v=<id>&gallery=<id> Single image view with prev/next nav
GET /watch?v=<id> Video player
GET /video/raw?v=<id> Stream video file
GET /video/thumbnail?v=<id> Thumbnail for any media (video or image)
GET /image/raw?v=<id> Full-size raw image file
GET /history User watch history
GET /account Account page
GET /login Login form
POST /login Submit login
GET /passwd Change password form
POST /passwd Submit password change

Database Schema

Table Purpose
videos Core video metadata
youtube_meta Embedded YouTube metadata
youtube_meta_tags Tags (many-to-many)
youtube_meta_categories Categories (many-to-many)
video_thumbnail Stored thumbnail data
users User accounts
user_session Active sessions
video_history Per-user watch history

Migrations are applied automatically on startup.

Use Cases

  • Personal video archive with search and browsing
  • Archiving yt-dlp downloads with preserved metadata
  • Image gallery server for a local photo or art collection
  • Internal media hosting for a small team
  • Building a custom frontend on top of the JSON API — a YouTube-style video browser, TikTok-style image feed, gallery viewer, etc.