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

@@ -394,6 +394,19 @@ def create_event():
session.commit()
event_media_id = media.id
# Video: event_media_id und Video-Einstellungen übernehmen
autoplay = None
loop = None
volume = None
if event_type == "video":
event_media_id = data.get("event_media_id")
if not event_media_id:
return jsonify({"error": "event_media_id required for video"}), 400
# Get video-specific settings with defaults
autoplay = data.get("autoplay", True)
loop = data.get("loop", False)
volume = data.get("volume", 0.8)
# created_by aus den Daten holen, Default: None
created_by = data.get("created_by")
@@ -419,6 +432,9 @@ def create_event():
is_active=True,
event_media_id=event_media_id,
slideshow_interval=slideshow_interval,
autoplay=autoplay,
loop=loop,
volume=volume,
created_by=created_by,
# Recurrence
recurrence_rule=data.get("recurrence_rule"),
@@ -491,6 +507,13 @@ def update_event(event_id):
event.event_type = data.get("event_type", event.event_type)
event.event_media_id = data.get("event_media_id", event.event_media_id)
event.slideshow_interval = data.get("slideshow_interval", event.slideshow_interval)
# Video-specific fields
if "autoplay" in data:
event.autoplay = data.get("autoplay")
if "loop" in data:
event.loop = data.get("loop")
if "volume" in data:
event.volume = data.get("volume")
event.created_by = data.get("created_by", event.created_by)
# Track previous values to decide on exception regeneration
prev_rule = event.recurrence_rule