feat(video): short-lived signed URLs for original-quality playback

POST /video/original mints a URL for one video's original bytes, signed
with a key derived from SECRET_KEY (distinct from the login-token key)
and valid for 6 hours. GET /video/original/stream?token= serves it via
NamedFile, so Range/seek works, without an Authorization header — native
players can use it directly. HLS stays the default path.

Also extracts generate_video's library fallback into resolve_request_path
and fixes the stale /video/stream entry in CLAUDE.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-10-13 20:42:28 -04:00
1 parent 4745a945fe
commit 40c33c41a6
5 files changed
+345 -29

No files matched your search

+7 -3
View File
@@ -525,9 +525,13 @@ GET /photos?path=...&recursive=true&sort=DateTakenDesc&camera_make=Canon&gps_lat
// ExifDao::query_by_exif — shared by /photos, /photos/exif and unified search.
// A calendar-day range = that day's bounds in the owner's display zone.
// Video streaming (HLS)
POST /video/generate (creates .m3u8 playlist + .ts segments)
GET /video/stream?path=... (serves playlist)
// Video streaming (HLS, the default playback path)
POST /video/generate (queues .m3u8 playlist + .ts segments, returns playlist_url)
GET /video/hls/<hash>/<file> (serves playlist / segments)
// Original-quality video (opt-in; short-lived signed URL, no auth header needed)
POST /video/original (body: {path, library}) -> {url, expires_at}
GET /video/original/stream?token=... (Range-capable original bytes)
// Tags
GET /image/tags/all