Digital Signage SaaS — Guía Completa
Digital Signage SaaS — Guía Completa
Versión: v1.0.52 Última actualización: 12-04-2026 App:
signage/(CMS) +monitoring/(monitoreo + publish endpoints)
1. Visión General
CreaRack Pro incluye un sistema completo de Digital Signage SaaS (“Super-Elementi”) que permite:
- Gestionar contenido multimedia (imágenes, vídeos, texto, colores, tickers, HTML5, web URLs, live streams)
- Crear playlists visuales con drag & drop, duración por item, fade transitions
- Programar schedules con reglas por hora, día, fecha y prioridad
- Publicar contenido a SpinetiX via Scheduled Download (sin Elementi)
- Deploy masivo a 60+ dispositivos con wizard de 3 pasos + progress bar
- Auto-configurar SpinetiX via Agent (CSRF form POST al Control Center)
- Auto-refresh del SpinetiX tras publicar (descarga inmediata)
- Monitorear dispositivos con SNMP (CPU, memory, bandwidth, charts en tiempo real)
- Portal de clientes con token, PIN, permisos granulares y approval workflow
- Preview en tiempo real del contenido SVG en el device detail
- Controlar displays remotamente (Samsung MDC, LG Protocol, PJLink)
- Verificar reproducción con proof-of-play y screenshots automáticos
Arquitectura
┌────────────────────────────────────────────────────────────┐
│ CreaRack Pro SaaS │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ │
│ │ Content │ │ Playlist │ │ Schedule │ │ Deploy │ │
│ │ Manager │→ │ Builder │→ │ Engine │→ │ Wizard │ │
│ └──────────┘ └──────────┘ └──────────┘ └─────┬─────┘ │
│ │ │
│ ┌─────────────────┐ ┌──────────────────────────┤ │
│ │ SVG Composer │ │ Publish Service │ │
│ │ (project.svg) │ │ /publish/{token}/ │ │
│ └────────┬────────┘ │ spx-listing.xml │ │
│ │ │ project.svg + media │ │
│ │ └──────────────────────────┘ │
│ ↓ ↓ │
│ ┌─────────────────┐ ┌──────────────────────────┐ │
│ │ Client Portal │ │ Local Agent (LAN) │ │
│ │ /client/{token} │ │ WebDAV PUT + Configure │ │
│ └─────────────────┘ └────────────┬─────────────┘ │
│ ↓ │
│ ┌──────────────────────┐ │
│ │ SpinetiX HMP │ │
│ │ Scheduled Download │ │
│ │ ← pulls content │ │
│ └──────────────────────┘ │
└────────────────────────────────────────────────────────────┘
2. Acceso
| URL | Descripción |
|---|---|
/monitoring/signage/ | Página principal Digital Signage |
/api/signage/ | API endpoints (48 endpoints) |
/api/docs | Swagger UI con todos los endpoints |
/admin/signage/ | Admin Django (7 modelos) |
Tabs Disponibles
| Tab | Función |
|---|---|
| Overview | Dashboard: métricas fleet (Total/Online/CPU/Content Synced), Bandwidth In/Out charts, health rings, rankings, heatmap 24h |
| Content | Media library: upload drag-drop, grid thumbnails, tags, preview modal, Add URL (web pages + streams), Publish (auto-configura SpinetiX), Deploy Selected (WebDAV push via Agent) |
| Playlists | Visual playlist builder: split-panel modal (media library 60% + playlist items 40%), drag & drop, items tipo imagen/texto/ticker/color, duraciones individuales, fade transitions |
| Schedules | Programación temporal con reglas (time_range, day_of_week, date_range, always), prioridades, timezone, default playlist |
| Deploy | Wizard 3 pasos: seleccionar contenido (playlist/schedule) → seleccionar devices (checkbox, Select All) → review + deploy con progress bar en tiempo real |
| Clients | Gestión de share links para portal externo: CRUD, permisos (4 niveles), PIN, expiración, approval workflow, cola de aprobaciones |
| CNS | AI Insights (anomalías, recomendaciones) |
| ITSM | Gestión de incidentes, SLA, escalamiento |
Device Detail (click en sidebar)
Al seleccionar un dispositivo en la sidebar, se abre un tab con:
- Hardware + Status + Port Connection en una fila (3 columnas)
- Content Preview — iframe 16:9 del project.svg servido al SpinetiX
- Charts — 4 panels fijos: CPU, Memory, Ping Latency, Bandwidth (In+Out dual), crosshair sincronizado
- Network — tabla de interfaces con velocidad y estado
3. Gestión de Contenido (Content Tab)
3.1 Subir Archivos
Métodos de upload:
- Drag & Drop: Arrastra archivos directamente a la zona de drop
- Botón Upload: Click en “Upload” y selecciona archivos
Formatos soportados:
| Tipo | Formatos | Tamaño Máximo |
|---|---|---|
| Imagen | JPEG, PNG, GIF, WebP, SVG, BMP, TIFF | 50 MB |
| Vídeo | MP4, WebM, MOV, AVI, MKV, OGG | 2 GB |
| HTML5 | HTML, ZIP | 100 MB |
| Web URL | http://, https:// | N/A (sin archivo) |
| Live Stream | rtsp://, rtp://, udp://, rtmp:// | N/A (sin archivo) |
3.2 Añadir URLs y Streams
El botón “Add URL” en el Content tab permite registrar páginas web y streams como contenido sin subir archivos.
Flujo:
- Click en “Add URL” → modal con campos Name, URL, Type (Web URL / Live Stream), Tags
- El backend crea un
MediaAssetconasset_type='url'o'stream',file_path=URL,status='ready' - El asset aparece en el grid con badge URL (violeta) o LIVE (cyan) y la dirección como texto
- Sin duración — URLs y streams se muestran indefinidamente hasta cambio de contenido
SVG rendering en SpinetiX:
- Web URL: Genera
<iframe src="URL" frameWidth="1920" frameHeight="1080">— el SpinetiX renderiza la web con su motor Chromium integrado - Live Stream: Genera
<video xlink:href="URL" spx:buffering="3" spx:silent="true">— playback continuo sin duración fija. Para RTSP se añadespx:transport="tcp"
Protocolos de streaming soportados por SpinetiX:
- RTSP (Real Time Streaming Protocol) — cámaras IP, encoders
- RTP (Real-time Transport Protocol) — multicast
- UDP — streams multicast directos
- SDP (Session Description Protocol)
Nota: HLS (
.m3u8) NO está soportado nativamente por SpinetiX HMP. Para streams HTTP usar MP4 directo o RTSP. El SpinetiX necesita acceso de red al servidor de streaming.
Endpoints API:
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/media/url | POST | Crear asset URL/stream (body: name, url, asset_type, tags) |
3.3 Procesamiento Automático
Al subir un archivo, Huey ejecuta en background:
- Auto-detección de tipo: El backend corrige
asset_typesegún MIME (video/mp4→'video'), independientemente de lo que envíe el frontend - Extracción de metadatos: Resolución, duración, codec, bitrate, fps (ffprobe para vídeo, Pillow para imagen)
- Generación de thumbnail:
- Imágenes: Pillow LANCZOS → 320px JPEG (quality 85)
- Vídeos: ffmpeg extrae frame en
00:00:02→ 320px JPEG (-vframes 1 -vf scale=320:-1)
- Transcodificación (solo vídeos):
- 1080p H.264 — compatibilidad universal
- 720p H.264 — players con ancho de banda limitado
- 4K H.265 — displays de alta resolución (solo si fuente ≥ 4K)
3.3 Gestión de Assets
- Grid/List toggle: Botones en el toolbar alternan entre vista de cuadrícula (cards con thumbnail 140px) y lista compacta (filas con thumbnail 48px, type badge, nombre, tamaño, duración). Preferencia persistida en
localStorage - Filtrar por tipo (imagen/vídeo/HTML5) o por tag
- Tags: Asigna etiquetas para organizar contenido
- Preview: Click en un asset para ver detalles, metadatos y variantes transcodificadas
- Publish/Delete: Botones con estilos centralizados (
btn-xs btn-success/btn-xs btn-danger) en cada card/fila - Modales: Cierre solo via botón X o Cancel — no se cierran al hacer click fuera del modal (click-outside dismiss deshabilitado)
- Reprocess: Si un asset muestra error, click “Retry” para re-procesar
- Bulk Delete: Selecciona múltiples assets y elimínalos de una vez
3.4 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/media/upload | POST | Upload con multipart/form-data |
/api/signage/signage/media | GET | Listar assets (filtros: asset_type, tag, status) |
/api/signage/signage/media/stats | GET | Estadísticas (conteo por tipo, tamaño total) |
/api/signage/signage/media/tags | GET | Lista de tags únicos |
/api/signage/signage/media/{id} | GET | Detalle de un asset |
/api/signage/signage/media/{id} | PATCH | Actualizar nombre/tags |
/api/signage/signage/media/{id} | DELETE | Eliminar asset + archivos |
/api/signage/signage/media/{id}/reprocess | POST | Re-procesar (thumbnail + transcode) |
/api/signage/signage/media/{id}/transcode-status | GET | Estado de transcodificación |
/api/signage/signage/media/{id}/thumbnail | POST | Regenerar thumbnail |
/api/signage/signage/media/bulk-delete | POST | Eliminar múltiples assets |
/api/signage/signage/media/url | POST | Crear asset URL o stream (sin archivo) |
4. Playlists (Playlists Tab)
4.1 Crear Playlist
- Click “New Playlist”
- Asigna nombre y descripción
- Define items en formato JSON:
[
{"asset_id": 1, "duration_seconds": 10, "transition": "fade", "order": 1},
{"asset_id": 2, "duration_seconds": 15, "transition": "none", "order": 2},
{"asset_id": 3, "duration_seconds": 20, "transition": "slide", "order": 3}
]
- Activa/desactiva Loop (reproducción continua)
- Click Save
4.2 Transiciones Disponibles
| Transición | Descripción |
|---|---|
none | Corte directo |
fade | Fundido a negro |
slide | Deslizamiento lateral |
dissolve | Disolución cruzada |
4.3 Operaciones
- Edit: Modifica items, nombre o configuración
- Duplicate: Crea una copia para variantes
- Preview: Visualiza la playlist con thumbnails y metadatos de cada asset
- Delete: Elimina la playlist (no elimina los assets)
4.4 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/playlists | GET | Listar playlists |
/api/signage/signage/playlists | POST | Crear playlist |
/api/signage/signage/playlists/{id} | GET | Detalle |
/api/signage/signage/playlists/{id} | PATCH | Actualizar |
/api/signage/signage/playlists/{id} | DELETE | Eliminar |
/api/signage/signage/playlists/{id}/duplicate | POST | Duplicar |
/api/signage/signage/playlists/{id}/preview | GET | Preview con asset details |
5. Schedules (Schedules Tab)
5.1 Crear Schedule
Un schedule define cuándo se reproduce qué playlist, usando reglas con prioridad.
{
"name": "Horario Laboral",
"timezone": "Europe/Madrid",
"default_playlist_id": 1,
"rules": [
{
"type": "day_of_week",
"days": [0, 1, 2, 3, 4],
"start": "09:00",
"end": "18:00",
"playlist_id": 2,
"priority": 10
},
{
"type": "time_range",
"start": "12:00",
"end": "14:00",
"playlist_id": 3,
"priority": 20
}
]
}
5.2 Tipos de Reglas
| Tipo | Campos | Ejemplo |
|---|---|---|
always | playlist_id, priority | Siempre activa (baja prioridad) |
time_range | start, end, playlist_id, priority | 09:00-18:00 horario laboral |
day_of_week | days[], start, end, playlist_id, priority | Lunes-Viernes + rango horario |
date_range | start_date, end_date, playlist_id, priority | Campaña navideña 15-31 dic |
Días: 0=Lunes, 1=Martes, …, 6=Domingo (ISO weekday)
5.3 Evaluación de Prioridad
El engine evalúa las reglas así:
- Filtra por ventana de validez (
valid_from/valid_until) - Filtra reglas que matchean con el momento actual
- Selecciona la de mayor prioridad
- Si ninguna matchea → usa la
default_playlist
Ejemplo: Con prioridad 20 (almuerzo) y 10 (horario laboral), entre 12:00-14:00 gana la de almuerzo.
5.4 Soporte SMIL
Los schedules se pueden exportar a formato SMIL XML (W3C 3.0) para players SpinetiX e IAdea que usan SMIL nativo.
5.5 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/schedules | GET | Listar schedules |
/api/signage/signage/schedules | POST | Crear schedule |
/api/signage/signage/schedules/{id} | GET | Detalle |
/api/signage/signage/schedules/{id} | PATCH | Actualizar |
/api/signage/signage/schedules/{id} | DELETE | Eliminar |
/api/signage/signage/schedules/{id}/active-playlist | GET | Playlist activa ahora |
6. Despliegue de Contenido (Deployments)
6.1 Flujo de Deployment
Crear Deployment → Asignar Players → Huey Task (async)
│
├→ Resolver adapter por player
├→ Descifrar credenciales (Fernet AES)
├→ Push archivos via VAL (WebDAV, REST, Cloud API)
├→ Set playlist/schedule via VAL
└→ Guardar resultados por player
6.2 Estados
| Estado | Significado |
|---|---|
pending | Creado, esperando ejecución |
deploying | En progreso |
deployed | Todos los players OK |
partial | Algunos players fallaron |
failed | Todos fallaron |
6.3 Retry
Los deployments failed o partial se pueden reintentar con el endpoint de retry.
6.4 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/deployments | POST | Crear deployment |
/api/signage/signage/deployments | GET | Listar deployments |
/api/signage/signage/deployments/{id} | GET | Estado y resultados |
/api/signage/signage/deployments/{id}/retry | POST | Reintentar |
/api/signage/signage/deployments/{id} | DELETE | Eliminar registro |
/api/signage/signage/deployments/{id}/results | GET | Resultados per-player |
7. Control de Displays
7.1 Protocolos Soportados
| Protocolo | Puerto | Vendors | Capacidades |
|---|---|---|---|
| Samsung MDC | TCP:1515 | Samsung | Power, Volume, Brightness, Input |
| LG Protocol | TCP:9761 | LG | Power, Volume, Brightness, Input |
| PJLink | TCP:4352 | Barco, Christie, NEC/Sharp | Power, Input, Mute, Status |
7.2 Fuentes de Entrada
Cada protocolo soporta distintas entradas: hdmi1, hdmi2, hdmi3, hdmi4, dp, dp2, dvi, vga, url, etc.
7.3 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/players/{id}/power-on | POST | Encender display |
/api/signage/signage/players/{id}/power-off | POST | Apagar display |
/api/signage/signage/players/{id}/volume | POST | Volumen (0-100) |
/api/signage/signage/players/{id}/brightness | POST | Brillo (0-100) |
/api/signage/signage/players/{id}/input | POST | Cambiar entrada |
/api/signage/signage/players/{id}/reboot | POST | Reiniciar player |
Body para volume/brightness: {"level": 75}
Body para input: {"source": "hdmi1"}
8. Proof of Play
8.1 Recolección Automática
Huey ejecuta automáticamente:
- Cada 15 minutos: Recolecta logs de reproducción de todos los players online
- Cada 30 minutos: Captura screenshots de players con capacidad de screenshot
- Diario (3:00 AM): Limpieza de screenshots >30 días y logs >90 días
8.2 Reportes
Tres formatos disponibles:
| Formato | Endpoint | Uso |
|---|---|---|
| JSON | /api/signage/signage/reports/proof-of-play | Integración con dashboards |
| HTML | /api/signage/signage/reports/proof-of-play/html | Visualización + impresión |
| CSV | /api/signage/signage/reports/proof-of-play/csv | Excel, análisis de datos |
Parámetros: ?days=7&player_id=5
8.3 Estadísticas
El endpoint /api/signage/signage/playback-stats devuelve:
- Total de horas de reproducción
- Top 10 players por actividad
- Top 10 assets más reproducidos
8.4 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/playback-logs | GET | Listar logs (filtros: player_id, days, limit) |
/api/signage/signage/playback-stats | GET | Estadísticas agregadas |
/api/signage/signage/playback-logs/collect | POST | Trigger manual de recolección |
/api/signage/signage/screenshots/capture | POST | Trigger manual de screenshots |
/api/signage/signage/players/{id}/screenshot | GET | Último screenshot de un player |
/api/signage/signage/reports/proof-of-play | GET | Reporte JSON |
/api/signage/signage/reports/proof-of-play/html | GET | Reporte HTML standalone |
/api/signage/signage/reports/proof-of-play/csv | GET | Reporte CSV (download) |
9. Players y Vendor Adapters
9.1 Registrar un Player
POST /api/signage/signage/players
{
"display_name": "Lobby Display 1",
"location": "Edificio A, Planta Baja",
"adapter_id": 1,
"device_profile_id": 42,
"api_credentials": {
"username": "admin",
"password": "secreto123"
}
}
Las credenciales sensibles (password, api_key, secret, token) se cifran automáticamente con Fernet AES-128.
9.2 Vendors Soportados (12)
| Vendor | Tipo | Content Push | Display Control |
|---|---|---|---|
| SpinetiX | JSON-RPC | WebDAV | — |
| BrightSign | REST | Cloud API | — |
| Samsung | REST | MagicINFO | MDC TCP:1515 |
| LG | REST | SuperSign | TCP:9761 |
| Crestron | REST | Upload | CIP |
| Philips | REST | Wave/CMND | SICP |
| IAdea | REST | SMIL HTTP | — |
| Barco | REST | Upload | PJLink |
| Christie | REST | Upload | PJLink |
| NEC/Sharp | REST | Upload | PJLink |
| Yodeck | REST | Cloud API | — |
| Signagelive | REST | Cloud API | — |
9.3 Auto-Provision
Los players detectados via SNMP en Auto-Provision (Step 3) se pueden enviar directamente al Digital Signage Monitor con la tarjeta “Send to Digital Signage”.
9.4 Endpoints API
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/players | GET | Listar players |
/api/signage/signage/players | POST | Registrar player |
/api/signage/signage/players/{id} | GET | Detalle |
/api/signage/signage/players/{id} | PATCH | Actualizar |
/api/signage/signage/players/{id} | DELETE | Eliminar |
/api/signage/signage/adapters | GET | Listar adapters disponibles |
10. Referencia Rápida
Modelos
| Modelo | Scope | Descripción |
|---|---|---|
SignageVendorAdapter | Global | Config por vendor (12 seeded) |
SignagePlayer | Org | Player físico vinculado a DeviceProfile |
MediaAsset | Org | Contenido multimedia (imagen/vídeo/HTML5/URL/stream) |
Playlist | Org | Colección ordenada de assets |
Schedule | Org | Reglas temporales → playlists |
PlaybackLog | Org | Registro de reproducción (alto volumen) |
ContentDeployment | Org | Tracking de despliegues a players |
ClientShareLink | Org | Link compartible para clientes externos (token UUID) |
PortalChangeLog | Org | Auditoría + cola de aprobación del portal |
Huey Tasks
| Task | Frecuencia | Función |
|---|---|---|
process_media_asset | On upload | Thumbnail + metadata + transcode |
run_deployment | On demand | Push content via VAL |
collect_playback_logs | Cada 15 min | Recolectar logs de players |
capture_screenshots | Cada 30 min | Capturar screenshots |
cleanup_old_data | Diario 3AM | Limpiar screenshots 30d + logs 90d |
Estructura de Archivos
signage/
├── models.py — 7 modelos core + imports portal
├── models_portal.py — 2 modelos portal (ClientShareLink, PortalChangeLog)
├── admin.py — Admin para 9 modelos
├── apps.py — AppConfig
├── tasks.py — 5 Huey tasks
├── views.py — Client portal view (public, token-based)
├── urls.py — /client/<token> route
├── api/
│ ├── __init__.py — Router assembly (10 sub-routers)
│ ├── schemas.py — Pydantic schemas
│ ├── content.py — 11 endpoints media CRUD
│ ├── players.py — 6 endpoints player CRUD
│ ├── playlists.py — 7 endpoints playlist CRUD
│ ├── schedules.py — 6 endpoints schedule CRUD
│ ├── deployments.py — 6 endpoints deployment
│ ├── display_control.py — 6 endpoints display control
│ ├── proof_of_play.py — 8 endpoints proof-of-play
│ ├── share_links.py — 6 endpoints link management
│ ├── portal.py — 12 endpoints client portal (public)
│ └── approvals.py — 4 endpoints approval workflow
├── services/
│ ├── file_storage.py — Upload, validación, paths
│ ├── thumbnail.py — Pillow + ffmpeg thumbnails
│ ├── transcode.py — ffmpeg H.264/H.265 pipeline
│ ├── deployment.py — Push content via VAL
│ ├── adapters/
│ │ ├── base.py — Abstract SignageDeviceAdapter
│ │ ├── registry.py — Factory: resolve by slug
│ │ ├── spinetix.py — JSON-RPC + WebDAV
│ │ ├── brightsign.py — BSN.cloud REST
│ │ ├── samsung.py — MagicINFO API
│ │ ├── lg.py — SuperSign API
│ │ └── generic_snmp.py — Fallback SNMP-only
│ ├── scheduling/
│ │ ├── engine.py — Evaluate rules → active playlist
│ │ └── smil_generator.py — JSON → SMIL XML
│ ├── display_control/
│ │ ├── samsung_mdc.py — TCP:1515 binary
│ │ ├── lg_protocol.py — TCP:9761 ASCII
│ │ ├── pjlink.py — TCP:4352 standard
│ │ └── controller.py — Unified dispatcher
│ └── proof_of_play/
│ ├── collector.py — Fetch logs via VAL
│ ├── screenshot.py — Capture + cleanup
│ └── reporter.py — JSON/HTML/CSV reports
└── migrations/
├── 0001_initial.py — 7 modelos core
├── 0002_seed_adapters.py — 12 vendor adapters
├── 0003_portal_share_links.py — ClientShareLink + PortalChangeLog
└── 0004_portal_approval_fields.py — Approval workflow fields
11. Client Portal (Share Links)
11.1 Concepto
El Client Portal permite a clientes externos editar contenido de señalización digital sin necesidad de cuenta CreaRack. El equipo técnico genera un link compartible con permisos específicos; el cliente abre el link y puede subir imágenes, modificar playlists y schedules.
11.2 Crear un Share Link
POST /api/signage/signage/share-links
{
"name": "Hotel Marriott - Lobby",
"client_name": "Juan García",
"client_email": "juan@marriott.com",
"pin": "1234",
"permission_level": "playlist",
"require_approval": true,
"playlist_ids": [1, 2],
"player_ids": [5, 6],
"schedule_ids": [3]
}
URL resultante: https://crearack.com/client/<uuid-token>
11.3 Niveles de Permiso
| Nivel | Subir contenido | Editar playlist | Editar schedule | Ver players |
|---|---|---|---|---|
view_only | Si | |||
content_only | Si | Si | ||
playlist | Si | Si | Si | |
schedule | Si | Si | Si | Si |
11.4 Modo Aprobación
Cuando require_approval = true:
- Los cambios del cliente se guardan como pendientes (no se aplican)
- El equipo técnico ve los cambios en
/api/signage/signage/approvals/pending - Puede aprobar (se aplica el cambio) o rechazar (con nota explicativa)
- El cliente ve el estado en su historial
11.5 Seguridad
| Aspecto | Implementación |
|---|---|
| Autenticación | Token UUID en la URL (no necesita login) |
| PIN opcional | 4-10 dígitos verificados antes de acceder |
| Expiración | Fecha de expiración configurable |
| Revocación | is_active = false invalida inmediatamente |
| Scoping | Solo ve players, playlists y schedules asignados |
| Audit trail | Toda acción registrada con IP + timestamp |
| CSP | Página standalone, skip CSP (no tiene acceso a rutas internas) |
11.6 Lo que el cliente ve
El portal es una página web standalone (dark theme, responsive) con:
- Displays: Estado de sus pantallas (online/offline)
- Upload: Drag-drop para subir imágenes y vídeos
- Playlists: Items con thumbnails, nombres y duraciones
- Media Library: Grid con todos los assets disponibles
- Historial: Cambios realizados y su estado (applied/pending/approved/rejected)
11.7 Endpoints API — Share Links (equipo técnico, autenticado)
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/share-links | GET | Listar links |
/api/signage/signage/share-links | POST | Crear link |
/api/signage/signage/share-links/{id} | GET | Detalle |
/api/signage/signage/share-links/{id} | PATCH | Actualizar |
/api/signage/signage/share-links/{id} | DELETE | Eliminar |
/api/signage/signage/share-links/{id}/logs | GET | Ver historial de cambios |
11.8 Endpoints API — Client Portal (público, token-based)
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/client-portal/{token}/info | GET | Info y permisos |
/api/signage/client-portal/{token}/verify-pin | POST | Verificar PIN |
/api/signage/client-portal/{token}/players | GET | Players asignados |
/api/signage/client-portal/{token}/playlists | GET | Playlists asignadas |
/api/signage/client-portal/{token}/schedules | GET | Schedules asignados |
/api/signage/client-portal/{token}/media | GET | Assets de las playlists |
/api/signage/client-portal/{token}/media/upload | POST | Subir archivo |
/api/signage/client-portal/{token}/playlists/{id} | PATCH | Modificar playlist |
/api/signage/client-portal/{token}/playlists/{id}/replace-asset | POST | Reemplazar asset |
/api/signage/client-portal/{token}/schedules/{id} | PATCH | Modificar schedule |
/api/signage/client-portal/{token}/history | GET | Historial de cambios |
/api/signage/client-portal/{token}/pending-count | GET | Cambios pendientes |
12. SpinetiX Integration (Scheduled Download)
Documentación técnica completa:
Documentation/backend/SPINETIX_INTEGRATION.md
12.1 Protocolo de Publicación
CreaRack actúa como servidor de contenido para SpinetiX via Scheduled Download:
- CreaRack genera dinámicamente
spx-listing.xml(WebDAV multistatus) +project.svg+ media files - El SpinetiX descarga desde
https://crearack.com/publish/{token}/ - El contenido se actualiza automáticamente en cada ciclo (hourly) o inmediatamente tras Publish
12.2 Endpoints Públicos (sin autenticación)
| Endpoint | Descripción |
|---|---|
GET /publish/{token}/ | Root — devuelve 501 para forzar fallback a spx-listing.xml |
GET /publish/{token}/spx-listing.xml | Índice WebDAV DAV:multistatus de todos los ficheros |
GET /publish/{token}/project.svg | Proyecto SVG dinámico (slideshow con transitions) |
GET /publish/{token}/index.svg | Alias de project.svg (entry point SpinetiX) |
GET /publish/{token}/{filename} | Media asset file |
12.3 SVG Composer
Módulo signage/services/svg_composer.py genera project.svg con soporte para:
| Tipo | Descripción | SVG Element |
|---|---|---|
image | Imagen fullscreen con preserveAspectRatio | <image> |
video | Vídeo con duración real del asset | <video> |
url | Página web renderizada por motor Chromium del SpinetiX | <iframe src="..." frameWidth frameHeight> |
stream | Stream en vivo (RTSP/RTP/UDP), sin duración, playback continuo | <video spx:buffering="3" spx:silent="true"> |
text | Texto con font, color, background rect | <text> |
color | Slide de color sólido | <rect> |
ticker | Texto scrolling horizontal (always-visible overlay) | <text> + <animateTransform> |
overlay | Imagen siempre visible (logo, watermark) | <image> |
Transiciones: transition: 'fade' usa opacity animate (0.5s crossfade), 'none' usa visibility discrete. URL y stream no participan en transiciones de timing — se muestran indefinidamente.
12.4 Auto-Configure via Agent
El Agent (POST /signage/configure) configura el SpinetiX automáticamente:
- GET Control Center → extrae CSRF cookie (URL-decode)
- POST form con Server URI + update mode
- POST con
update=nowpara forzar descarga inmediata
12.5 Flujo Completo de Publish
1. Usuario: Content tab → Publish → selecciona devices + playlist
2. SaaS: Crea SignagePlayer, genera publish URL, vincula playlist
3. Agent: Configura Scheduled Download en SpinetiX (CSRF + form POST)
4. Agent: Fuerza descarga inmediata (update=now)
5. SpinetiX: GET spx-listing.xml → GET project.svg → GET media files
6. SpinetiX: Muestra contenido en pantalla
7. Heartbeat: Cada fetch actualiza player.last_heartbeat + status
12.6 Monitoreo SNMP del SpinetiX
| Métrica | OID | Nota |
|---|---|---|
| CPU Usage | 1.3.6.1.2.1.25.3.3.1.2.196608 | Index no estándar (196608) |
| Memory Used | 1.3.6.1.2.1.25.2.3.1.6.1 | Valor en KB raw |
| Bandwidth | snmp_bandwidth_in/out_mbps | Via interface eth0 |
| Ping | ping_latency_ms | ICMP round-trip |
13. UX y Modales
13.1 SignageModalHelper
Módulo reutilizable SignageModalHelper.js reemplaza todos los prompt()/confirm() nativos:
import { SignageModal } from './SignageModalHelper.js';
// Input modal con campos configurables
const result = await SignageModal.input('Title', [
{ name: 'text', label: 'Content', type: 'text' },
{ name: 'color', label: 'Color', type: 'color', value: '#ffffff' },
{ name: 'size', label: 'Size', type: 'number', value: 48 },
{ name: 'option', label: 'Choice', type: 'select', options: [{value:'a',label:'A'}] },
]);
// Confirm modal
const ok = await SignageModal.confirm('Delete this item?', 'Delete');
// Alert modal (replaces native alert)
await SignageModal.alert('Active Playlist:\nRule matched...', 'Schedule Status');
// Device selection modal (groups + checkboxes + Select All)
const devices = await SignageModal.selectDevices('Publish "image.jpg"', 'Publish');
// Returns [{id, name, ip}, ...] or null if cancelled
Tipos de campo: text, password, number, color (con picker + hex input), select, textarea.
selectDevices() muestra un modal unificado con:
- Filtro por Groups (dropdown desde sidebar)
- Checkbox “All” para seleccionar/deseleccionar todos los visibles
- Lista de dispositivos con checkboxes, status dot (online/offline), nombre e IP
- Botón deshabilitado hasta seleccionar al menos un dispositivo
13.2 Playlist Builder
Modal split-panel (1500px × 90vh):
- Media Library (flex:3): Panel izquierdo ~50% con grid 3 columnas de thumbnails, type badges, search filter, upload directo
- Media/Transitions tabs: Toggle en el header del panel de library alterna entre:
- Media tab: Grid de assets disponibles (imágenes, vídeos, texto, colores)
- Transitions tab: 9 tarjetas arrastrables con los tipos de transición disponibles
- Playlist Items (flex:3): Panel derecho ~50%, lista ordenable con up/down/remove, duration input, type badges, transition badges entre slides
- Botones: Text (modal con font_size, color, bg_color — bg_color aplica fondo fullscreen via SVG fill + fill-opacity desde 8-digit hex alpha), Ticker (speed + colors), Color (color picker)
- Drag & Drop: HTML5 DnD desde library al panel de playlist. Las transiciones se arrastran entre slides o se hace click para añadir al final
- Click-to-edit: Click en nombre de item abre modal de edición con campos específicos por tipo
9 tipos de transición disponibles:
| Transición | SVG Implementation | Descripción |
|---|---|---|
| Cross Dissolve | opacity crossfade | Disolución cruzada entre slides |
| Fade to Black | opacity 1→0→1 | Fundido a negro entre slides |
| Slide Left | animateTransform translate | Deslizamiento hacia la izquierda |
| Slide Right | animateTransform translate | Deslizamiento hacia la derecha |
| Slide Up | animateTransform translate | Deslizamiento hacia arriba |
| Slide Down | animateTransform translate | Deslizamiento hacia abajo |
| Zoom In | animateTransform scale | Zoom de entrada |
| Zoom Out | animateTransform scale | Zoom de salida |
| Cut | visibility discrete | Corte directo (sin animación) |
Cada item almacena su propio tipo de transición + duración. Las transiciones se muestran como badges entre los slides en el panel de playlist.
Live Preview Monitor (footer del builder):
- Monitor 16:9 (160px de alto) que muestra preview en tiempo real del contenido
- Genera SVG via
POST /signage/playlists/preview-svgsin necesidad de publicar - URLs de media absolutas para renderizado inline correcto
- Botones Preview (play) y Stop para probar la animación de la playlist antes de publicar
Save & Publish: Botón que guarda la playlist y abre inmediatamente el modal de selección de dispositivos para publicar
13.3 Auto-Refresh SpinetiX (httpPublish)
Tras Publish, el Agent fuerza la descarga inmediata en el SpinetiX:
GET /→ sesión + CSRFPOST /user/loginconUserLogin[username/password]+X-Requested-With: XMLHttpRequestPOST /controlcenter/main/content→ guarda config Scheduled DownloadPOST /controlcenter/operation/httpPublishconaction=publish+ uri + CSRF +X-Requested-With: XMLHttpRequest
Clave: El header X-Requested-With: XMLHttpRequest es obligatorio — sin él el endpoint devuelve HTML en vez de ejecutar la acción AJAX.
13.4 Credenciales Automáticas
Módulo compartido SignageCredentials.js con función resolveSignageCredentials():
Flujo de resolución (3 pasos, primero que resuelve gana):
- sessionStorage → cache
signage_creds(persiste en la pestaña del navegador) - Credential Store API →
GET /api/credentials/busca primera credential con sección HTTP →GET /api/credentials/{id}/decryptobtiene username/password en plaintext - Modal prompt → solo si las dos anteriores están vacías (con hint “save in Config > Credentials to skip”)
Seguridad: El endpoint publish-setup NO devuelve passwords en la respuesta JSON. Las credenciales se resuelven exclusivamente en el frontend via la API de Credential Store.
Backend: StoredCredential.get_section('http') descifra automáticamente los campos sensibles con Fernet y devuelve {username, password}.
13.5 Publish Flow Completo (actualizado 25-03-2026)
1. Usuario: Click Publish en thumbnail (o botón Publish general)
2. Frontend: SignageModal.selectDevices() → modal unificado con:
- Filtro por Groups
- Checkbox "All" + checkboxes individuales
- Status dots (online/offline)
→ Devuelve array de dispositivos seleccionados
3. Frontend: resolveSignageCredentials() → 3-step chain
(sessionStorage → Credential Store API → modal prompt)
4. Por cada dispositivo seleccionado:
a. SaaS: POST /signage/publish-setup
→ Crea SignagePlayer + bind playlist/schedule
→ Devuelve publish_url (sin passwords)
b. Frontend: POST Agent /signage/configure con publish_url + creds
5. Agent:
a. GET / → sesión + CSRF
b. POST /user/login → autenticación Yii
c. POST /controlcenter/main/content → guarda Scheduled Download URL
d. POST /controlcenter/operation/httpPublish → descarga inmediata
6. SpinetiX: Descarga spx-listing.xml + project.svg + media
7. Pantalla: Muestra nuevo contenido (imágenes + vídeos)
Playback Settings: El modal incluye un panel fijo con Duration (1-300s), Loop, Transition (Fade/Cut), Pause between loops (0-60s) y Fit mode (Fill/Fit/Center). Los settings se guardan en SignagePlayer.display_info['playback'] y el SVG Composer los aplica al generar project.svg.
Auto-refresh preview: Tras publicar, se dispara un CustomEvent('signage-published') que fuerza el refresco automático del iframe de Content Preview en el device detail.
13.6 Soporte de Vídeo en SVG
El SVG Composer genera elementos <video> para SpinetiX con estas reglas:
- Auto-detección de tipo: Si
MediaAsset.asset_type == 'video', el item se renderiza como<video>aunque el playlist item diga'image' - Duración real: Los vídeos ignoran el Duration del modal y usan la duración real del archivo (extraída por ffprobe). Las imágenes sí respetan el Duration configurado
- Replay en loops: El
<video>se envuelve en un<g>con animación de visibility. El vídeo tienerepeatCount="indefinite"(siempre reproduciéndose internamente). El<g>controla cuándo es visible — esto garantiza replay correcto en cada pase del loop - Sin fade: Los vídeos usan animación de
visibility(show/hide discreto), noopacityfade — SpinetiX no soporta fade en<video>
<!-- Estructura SVG para vídeo en playlist mixta -->
<g visibility="hidden">
<animate attributeName="visibility" values="hidden;hidden;visible;hidden;hidden"
keyTimes="0;0.6;0.6;0.8;1" dur="30s" repeatCount="indefinite" calcMode="discrete"/>
<video x="0" y="0" width="1920" height="1080"
xlink:href="video.mp4" dur="5.87s"
preserveAspectRatio="xMidYMid slice" repeatCount="indefinite"/>
</g>
Hint en modal: El panel de Playback Settings muestra “Videos always play their full duration” para informar al usuario.
13.7 Clear Playback + Pause/Resume
Pause / Resume (botón btn-info en toolbar Content):
- Modal con lista de dispositivos mostrando estado: dot verde (playing) o badge PAUSED amarillo
- Dos botones de acción: Pause (congela frame) y Resume (reinicia contenido)
- Estado de pausa almacenado como
clear_action='pause'enplayer.display_info
Clear Playback (botón btn-warning):
- Modal unificado con selección de acción (radio cards) + selección de dispositivos (groups + checkboxes)
- 5 acciones disponibles:
| Acción | Color | Descripción |
|---|---|---|
| Corporate Image | Violeta | Imagen corporativa fullscreen — botón “Open”/“Change” para cargar, persistente por org |
| Black Screen | Gris | Pantalla negra |
| Test Pattern | Azul | Barras SMPTE + “CreaRack Test Pattern” |
| Restart Content | Verde | Fuerza re-descarga sin cambiar contenido |
| Clear All Content | Rojo | Elimina playlist/schedule, pantalla negra |
Corporate Image persistencia: El corporate_asset_id se guarda en player.display_info y se resuelve desde status-list al reabrir el modal. El upload fuerza tag corporate y reemplaza la imagen anterior (dedup automático).
13.8 Operation History (Rollback)
Sistema de caché-backup para recuperar operaciones en señalización crítica.
Modelo SignageOperation (migración signage/0006):
playerFK,operation_type,previous_stateJSON,new_stateJSON,performed_by,created_atprevious_stateguarda:playlist_id,schedule_id,display_infocompleto- Auto-purge: mantiene últimas 50 operaciones por organización
Auto-logging: Cada publish-setup y clear_action graba la operación antes de ejecutar.
Frontend: Botón “History” en toolbar → modal con tabla:
- Columnas: Time, Type (badge con color), Device, Description, User, Restore
- Botón Restore por fila → confirmación → revierte
previous_state→ httpPublish al Agent
API:
| Endpoint | Método | Descripción |
|---|---|---|
/api/monitoring/signage/operations | GET | Lista últimas 50 operaciones (soporta filtro source=content|playlist) |
/api/monitoring/signage/operations/{id}/restore | POST | Rollback a estado anterior + devuelve publish_url |
13.9 Playlist Tab
Tab autónomo dedicado exclusivamente a playlists creadas por el usuario (no auto-generadas).
Filtrado is_auto: Solo muestra playlists con is_auto=false. Las playlists auto-generadas (prefijo _auto_*) creadas por Publish from Content se ocultan automáticamente.
Toolbar autónomo con 4 acciones:
- Publish: Selecciona una playlist →
SignageModal.selectDevices()→ publica sin panel de Playback Settings (la playlist tiene sus propias duraciones por item) - Pause/Resume: Misma funcionalidad que Content tab (modal compartido)
- Clear Playback: Misma funcionalidad que Content tab (modal compartido)
- History: Modal de historial filtrado por
source=playlist— solo muestra operaciones originadas desde playlists reales. Columna “Name” muestra el nombre de la playlist
PUBLISHED badge: Badge verde en las playlists que están actualmente asignadas a players activos.
Real playlists preserve durations: Cuando se publica desde el Playlist tab, las duraciones configuradas en cada item se respetan. El override de Playback Settings (Duration) solo aplica a auto-playlists generadas desde Content.
Auto-purge: Las playlists _auto_* con más de 24h de antigüedad se eliminan automáticamente, manteniendo un máximo de 20 auto-playlists recientes.
14. Schedule Matrix (27-03-2026)
Visual scheduler with Day/Week/Month views for programming playlists on devices.
Views:
- Day: 24h timeline (
<table>layout), quarter/half-hour grid lines, red current-time cursor (updates 30s), click empty area to create - Week: 7-column (Mon-Sun) grid, compact pills per day, today highlighted red, click to create
- Month: Calendar grid, up to 3 blocks per cell, click to create, drill-down to Day
Schedule Block Modal:
- Device selector with group filter (checkboxes + All/None)
- Playlist selector
- Repeat: This day only / Every day / Every week / Every month / Custom days
- 7 clickable day pills (Mon-Sun) for Custom
- Time pickers (
input type="time") for minute precision - 10 color pills for custom block coloring
- Action at End: None / Black Screen / Corporate Image / Test Pattern
- Delete + Duplicate buttons (edit mode)
Auto-publishing:
- Blocks auto-save on every action (debounce 800ms, flush before navigation)
- Timer scheduled for each block’s start time →
publish-setup+ Agent httpPublish - End timer triggers end action (Black/Corporate/Test) when block finishes
- Timers activate on page load for existing blocks
Conflict Detection:
- Overlapping blocks on same device highlighted with red border + glow
- Tooltip shows “CONFLICT” label
- Works in all 3 views
15. History Tab (27-03-2026)
Replaces old Deploy tab. Full operation history dashboard.
- Filter by operation type (Publish, Pause, Black, etc.)
- Filter by device (auto-populated dropdown)
- Table: Time, Type (color badge), Device, Name, User
- View button: modal with full operation detail (previous/new state)
- Restore button: reverts player to previous state + httpPublish
16. Client Projects (27-03-2026)
Multi-client content management with isolated project scoping.
Model ClientProject (migration 0008):
- name, client_name, client_email, client_phone
- share_token (UUID), PIN (optional), is_active, expires_at
- devices M2M, playlists M2M
- permissions JSON:
{upload, reorder, schedule}
Admin (Clients tab):
- Project cards with status dot, client info, device/playlist counts, permissions
- Create/Edit modal: device checkboxes, playlist checkboxes, permission toggles
- Copy Link button copies
/client/{token}/URL
Client Portal (/client/{token}/):
- PIN gate page (session-based, one-time entry)
- Devices list, Playlists with Preview (SVG inline), Content grid with thumbnails
- Upload zone (drag & drop) for permitted clients
- New Playlist button (creates + auto-assigns to project)
- Publish button per playlist (select device → assigns to player)
- Self-contained dark theme page, no auth required
API Endpoints:
| Endpoint | Método | Descripción |
|---|---|---|
/api/signage/signage/client-projects | GET | List projects |
/api/signage/signage/client-projects | POST | Create project |
/api/signage/signage/client-projects/{id} | GET/PATCH/DELETE | CRUD |
/client/{token}/ | GET | Public portal page |
/client/{token}/upload | POST | Client file upload |
/client/{token}/create-playlist | POST | Client playlist creation |
/client/{token}/publish | POST | Client publish to device |
Mantenido por: Claude (Anthropic) + Equipo CreaRack
Véase también
- [[concept—signage—deployment]] — modelo de despliegue de Signage
- [[crearack—signage—que-es-signage]] — introducción a Digital Signage
- [[crearack—signage—pantallas]] — gestión de pantallas
- [[crearack—signage—playlists]] — playlists de Signage
- [[crearack—signage—contenido]] — contenido y assets de Signage
- [[crearack-tech—backend—spinetix-integration]] — integración con SpinetiX
- [[crearack-tech—agents—dev-signage]] — perfil de subagente dev-signage
- [[entity—signage—model—mediaasset]] — asset multimedia de Signage