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:
34
.github/copilot-instructions.md
vendored
34
.github/copilot-instructions.md
vendored
@@ -6,6 +6,30 @@ Prefer explanations and refactors that align with these structures.
|
||||
|
||||
Use this as your shared context when proposing changes. Keep edits minimal and match existing patterns referenced below.
|
||||
|
||||
## TL;DR
|
||||
Small multi-service digital signage app (Flask API, React dashboard, MQTT scheduler). Edit `server/` for API logic, `scheduler/` for event publishing, and `dashboard/` for UI. If you're asking Copilot for changes, prefer focused prompts that include the target file(s) and the desired behavior.
|
||||
|
||||
### How to ask Copilot
|
||||
- "Add a new route `GET /api/events/summary` that returns counts per event_type — implement in `server/routes/events.py`."
|
||||
- "Create an Alembic migration to add `duration` and `resolution` to `event_media` and update upload handler to populate them."
|
||||
- "Refactor `scheduler/db_utils.py` to prefer precomputed EventMedia metadata and fall back to a HEAD probe."
|
||||
- "Add an ffprobe-based worker that extracts duration/resolution/bitrate and stores them on `EventMedia`."
|
||||
|
||||
### When not to change
|
||||
- Avoid editing generated assets under `dashboard/dist/` and compiled bundles. Don't modify files produced by CI or Docker builds (unless intentionally updating build outputs).
|
||||
|
||||
### Contact / owner
|
||||
- Primary maintainer: RobbStarkAustria (owner). For architecture questions, ping the repo owner or open an issue and tag `@RobbStarkAustria`.
|
||||
|
||||
### Important files (quick jump targets)
|
||||
- `scheduler/db_utils.py` — event formatting and scheduler-facing logic
|
||||
- `scheduler/scheduler.py` — scheduler main loop and MQTT publisher
|
||||
- `server/routes/eventmedia.py` — file uploads, streaming endpoint
|
||||
- `server/routes/events.py` — event CRUD and recurrence handling
|
||||
- `dashboard/src/components/CustomEventModal.tsx` — event creation UI
|
||||
- `dashboard/src/media.tsx` — FileManager / upload settings
|
||||
|
||||
|
||||
## Big picture
|
||||
- Multi-service app orchestrated by Docker Compose.
|
||||
- API: Flask + SQLAlchemy (MariaDB), in `server/` exposed on :8000 (health: `/health`).
|
||||
@@ -15,6 +39,16 @@ Use this as your shared context when proposing changes. Keep edits minimal and m
|
||||
- Scheduler: Publishes only currently active events (per group, at "now") to MQTT retained topics in `scheduler/scheduler.py`. It queries a future window (default: 7 days) to expand recurring events using RFC 5545 rules and applies event exceptions, but only publishes events that are active at the current time. When a group has no active events, the scheduler clears its retained topic by publishing an empty list. All time comparisons are UTC; any naive timestamps are normalized. Logging is concise; conversion lookups are cached and logged only once per media.
|
||||
- Nginx: Reverse proxy routes `/api/*` and `/screenshots/*` to API; everything else to dashboard (`nginx.conf`).
|
||||
|
||||
## Recent changes since last commit
|
||||
|
||||
- Scheduler: when formatting video events the scheduler now performs a best-effort HEAD probe of the streaming URL and includes basic metadata in the emitted payload (mime_type, size, accept_ranges). Placeholders for richer metadata (duration, resolution, bitrate, qualities, thumbnails, checksum) are included for later population by a background worker.
|
||||
- Streaming endpoint: a range-capable streaming endpoint was added at `/api/eventmedia/stream/<media_id>/<filename>` that supports byte-range requests (206 Partial Content) to enable seeking from clients.
|
||||
- Event model & API: `Event` gained video-related fields (`event_media_id`, `autoplay`, `loop`, `volume`) and the API accepts and persists these when creating/updating video events.
|
||||
- Dashboard: UI updated to allow selecting uploaded videos for events and to specify autoplay/loop/volume. File upload settings were increased (maxFileSize raised) and the client now validates video duration (max 10 minutes) before upload.
|
||||
- FileManager: uploads compute basic metadata and enqueue conversions for office formats as before; video uploads now surface size and are streamable via the new endpoint.
|
||||
|
||||
Note: these edits are intentionally backwards-compatible — if the probe fails, the scheduler still emits the stream URL and the client should fallback to a direct play attempt or request richer metadata when available.
|
||||
|
||||
## Service boundaries & data flow
|
||||
- Database connection string is passed as `DB_CONN` (mysql+pymysql) to Python services.
|
||||
- API builds its engine in `server/database.py` (loads `.env` only in development).
|
||||
|
||||
Reference in New Issue
Block a user