feat(video): add streamable video events & dashboard controls

Add end-to-end support for video events: server streaming, scheduler
metadata, API fields, and dashboard UI.

- Server: range-capable streaming endpoint with byte-range support.
- Scheduler: emits `video` object; best-effort HEAD probe adds
  `mime_type`, `size`, `accept_ranges`; placeholders for richer
  metadata (duration/resolution/bitrate/qualities/thumbnails).
- API/DB: accept and persist `event_media_id`, `autoplay`, `loop`,
  `volume` for video events.
- Frontend: Event modal supports video selection + playback options;
  FileManager increased upload size and client-side duration check
  (max 10 minutes).
- Docs/UX: bumped program-info, added UX-only changelog and updated
  Copilot instructions for contributors.
- Notes: metadata extraction (ffprobe), checksum persistence, and
  HLS/DASH transcoding are recommended follow-ups (separate changes).
This commit is contained in:
RobbStarkAustria
2025-10-25 16:48:14 +00:00
parent e6c19c189f
commit 38800cec68
14 changed files with 453 additions and 83 deletions

View File

@@ -9,6 +9,11 @@ http {
server {
listen 80;
server_name _;
# Allow larger uploads (match Flask MAX_CONTENT_LENGTH); adjust as needed
client_max_body_size 1G;
# Increase proxy timeouts for long uploads on slow connections
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
# Leitet /api/ und /screenshots/ an den API-Server weiter
location /api/ {
@@ -17,6 +22,29 @@ http {
location /screenshots/ {
proxy_pass http://infoscreen_api/screenshots/;
}
# Public direct serving (optional)
location /files/ {
alias /opt/infoscreen/server/media/;
sendfile on;
tcp_nopush on;
types {
video/mp4 mp4;
video/webm webm;
video/ogg ogg;
}
add_header Accept-Ranges bytes;
add_header Cache-Control "public, max-age=3600";
}
# Internal location for X-Accel-Redirect (protected)
location /internal_media/ {
internal;
alias /opt/infoscreen/server/media/;
sendfile on;
tcp_nopush on;
add_header Accept-Ranges bytes;
add_header Cache-Control "private, max-age=0, s-maxage=3600";
}
# Alles andere geht ans Frontend
location / {
proxy_pass http://dashboard;