Módulo de Vigilancia
Integración CCTV, detección de movimiento, grabación de clips y vinculación de evidencia — detección FFmpeg del lado del servidor, superposición en navegador y almacenamiento en Nextcloud.
Última actualización: 2025-02-18
Módulo de Vigilancia
El módulo de Vigilancia conecta cámaras CCTV con la cadena de evidencia: transmisiones en vivo, grabación de clips activada por movimiento, detección de objetos opcional basada en navegador y vinculación automática con eventos del WHMS y la Máquina del Tiempo.
Vista General de la Cuadrícula de Cámaras
La cuadrícula de vigilancia 2x3 proporciona monitoreo de un vistazo de todas las cámaras del almacén. Haga clic en cualquier feed para expandir y ver metadatos detallados.
6 feeds de cámaras con estado de grabación, indicadores de detección de movimiento y asignaciones de zona.
Arquitectura
Principios de Diseño
- Servidor primero: La detección de movimiento y la extracción de clips se ejecutan en FFmpeg; el navegador muestra las transmisiones y los controles.
- Vinculado a evidencia: Los clips se suben a Nextcloud con metadatos (cámara, hora, duración) y pueden adjuntarse a eventos de colocación del WHMS.
- Detección en navegador opcional: TensorFlow.js COCO-SSD se ejecuta en el navegador solo para cajas de objetos; ningún frame sale del dispositivo.
Inventario de Componentes
Todos los componentes relacionados con vigilancia y sus roles.
Detección y control de movimiento
| Componente | Ruta | Descripción |
|---|---|---|
MotionClipControl | @/components/iot/motion-clip-control | Iniciar/detener detección por cámara, sensibilidad, pre/post grabación |
DetectionControlPanel | @/components/iot/detection-control-panel | Controles y ajustes de detección multi-cámara |
DetectionConfigPanel | @/components/iot/detection-config-panel | Reglas y taxonomía para detección |
DetectionDashboard | @/components/iot/detection-dashboard | Vista general de todas las cámaras y estado de movimiento |
DetectionToast | @/components/iot/detection-toast | Toast dentro de la app cuando se detecta movimiento |
Transmisiones y reproducción
| Componente | Ruta | Descripción |
|---|---|---|
CameraGrid | @/components/iot/camera-grid | Cuadrícula de transmisiones de cámara en vivo (HLS) |
EnhancedStreamPlayer | @/components/iot/enhanced-stream-player | Transmisión individual con controles y superposición |
EnhancedMotionViewer | @/components/iot/enhanced-motion-viewer | Transmisión + controles de movimiento + superposición TF opcional |
StreamPreview | @/components/iot/stream-preview | Miniatura de vista previa |
CctvStreamField | @/components/iot/cctv-stream-field | Campo de tabla/formulario para seleccionar y mostrar una transmisión |
Superposición de detección en navegador
| Componente | Ruta | Descripción |
|---|---|---|
BrowserDetectionOverlay | @/components/iot/browser-detection-overlay | Superposición TensorFlow.js COCO-SSD en video |
DetectionOverlay | @/components/iot/detection-overlay | Wrapper para superposición de detección |
BoundingBoxOverlay | @/components/iot/bounding-box-overlay | Dibuja cajas delimitadoras y etiquetas |
Clips y grabaciones
| Componente | Ruta | Descripción |
|---|---|---|
ClipRecorder | @/components/iot/clip-recorder | Graba desde transmisión a blob/clip |
ClipExportDialog | @/components/iot/clip-export-dialog | Exportar clip a Nextcloud o descargar |
SaveClipDialog | @/components/iot/save-clip-dialog | Guardar clip con metadatos |
RecordingsList | @/components/iot/recordings-list | Lista de clips guardados con reproducción |
SurveillanceTimeline | @/components/iot/surveillance-timeline | Línea de tiempo de eventos de movimiento y clips |
Integración con WHMS
| Componente | Ruta | Descripción |
|---|---|---|
ZoneCCTVTab | @/components/whms/ZoneCCTVTab | Feeds CCTV para una zona del WHMS |
CCTVTab | @/components/whms/CCTVTab | Lista de cámaras y estado en contexto WHMS |
CCTVWidget | @/components/workflow/widgets/CCTVWidget | Widget de flujo de trabajo para transmisión de cámara |
SurveillanceWidget | @/components/dashboard/SurveillanceWidget | Widget de dashboard para vigilancia |
Configuración y modales
| Componente | Ruta | Descripción |
|---|---|---|
CameraQuickSettings | @/components/iot/camera-quick-settings | Ajustes rápidos de una cámara |
CameraSettingsModal | @/components/iot/camera-settings-modal | Configuración completa de cámara |
IotCameraSelector | @/components/iot/IotCameraSelector | Seleccionar una cámara de la lista |
EventViewer | @/components/iot/event-viewer | Ver eventos de detección |
EventDetailModal | @/components/iot/event-detail-modal | Detalles de un evento individual y clip |
Campos y deck
| Componente | Ruta | Descripción |
|---|---|---|
CCTVField | @/components/fields/CCTVField | Renderizador de campo para referencia CCTV |
IotEvidenceField | @/components/fields/IotEvidenceField | Adjunto de evidencia IoT |
DeckIntegrationPanel | @/components/iot/deck-integration-panel | Vincular detección a tarjetas Deck |
SessionToRecordDialog | @/components/iot/session-to-record-dialog | Adjuntar sesión a registro de tabla |
Patrones de UI (sandboxes)
Estos sandboxes muestran los bloques de construcción de UI usados en la interfaz de vigilancia. Los componentes reales usan las mismas primitivas más elementos de video y estado de API.
Tarjeta de estado de cámara
Una cámara individual en una cuadrícula o lista: badge de estado, nombre y acciones.
<Card className="max-w-xs"> <CardHeader className="pb-2 flex flex-row items-center justify-between"> <CardTitle className="text-sm font-medium">Muelle de carga — Cam 3</CardTitle> <Badge variant="secondary">En vivo</Badge> </CardHeader> <CardContent className="space-y-3"> <div className="aspect-video rounded-md bg-muted flex items-center justify-center text-xs text-muted-foreground"> Vista previa de transmisión </div> <div className="flex gap-2"> <Button size="sm" variant="outline">Movimiento on</Button> <Button size="sm" variant="ghost">Ajustes</Button> </div> </CardContent> </Card>
Franja de control de movimiento
Iniciar/detener detección y sensibilidad (refleja MotionClipControl).
<Card className="max-w-md"> <CardHeader className="pb-2"> <CardTitle className="text-base">Detección de movimiento</CardTitle> <CardDescription>Cámara 3 — Muelle de carga</CardDescription> </CardHeader> <CardContent className="space-y-4"> <div className="flex items-center justify-between"> <span className="text-sm">Estado</span> <Badge variant="destructive">Grabando</Badge> </div> <div className="flex gap-2"> <Button size="sm">Detener</Button> <Button size="sm" variant="outline">Sensibilidad</Button> <Button size="sm" variant="outline">Buffer de clip</Button> </div> <Alert> <AlertTitle>Movimiento detectado</AlertTitle> <AlertDescription>Último evento hace 30s. Clip guardado.</AlertDescription> </Alert> </CardContent> </Card>
Fila de lista de clips
Una fila en la lista de grabaciones: miniatura, hora, duración, acciones.
<div className="flex items-center gap-4 rounded-lg border p-3 max-w-lg"> <div className="w-24 h-14 rounded bg-muted flex-shrink-0 flex items-center justify-center text-xs text-muted-foreground"> Miniatura </div> <div className="flex-1 min-w-0"> <p className="text-sm font-medium">Cam 3 — Muelle de carga</p> <p className="text-xs text-muted-foreground">14:32:05 · 12s</p> </div> <div className="flex gap-1"> <Button size="sm" variant="ghost">Reproducir</Button> <Button size="sm" variant="ghost">Exportar</Button> </div> </div>
Panel de alerta de detección
Alerta en la app cuando se detecta movimiento (estilo DetectionToast).
<Alert variant="default" className="max-w-md"> <AlertTitle>Movimiento detectado — Cam 2</AlertTitle> <AlertDescription> Área de preparación. Clip grabado y vinculado a evidencia. Abrir para ver. </AlertDescription> <div className="mt-2 flex gap-2"> <Button size="sm">Ver clip</Button> <Button size="sm" variant="outline">Descartar</Button> </div> </Alert>
Cuadrícula de cámaras (placeholder)
Cuadrícula de placeholders de cámaras (la cuadrícula real usa reproductores HLS).
<div className="grid grid-cols-2 gap-2 max-w-md"> <div className="aspect-video rounded-lg border bg-muted flex items-center justify-center text-xs text-muted-foreground">Cam 1</div> <div className="aspect-video rounded-lg border bg-muted flex items-center justify-center text-xs text-muted-foreground">Cam 2</div> <div className="aspect-video rounded-lg border bg-muted flex items-center justify-center text-xs text-muted-foreground">Cam 3</div> <div className="aspect-video rounded-lg border bg-muted flex items-center justify-center text-xs text-muted-foreground">Cam 4</div> </div>
Franja de resumen de vigilancia
Franja resumen: cámaras en línea, movimiento activo, clips recientes (estilo SurveillanceWidget).
<div className="flex flex-wrap gap-4 rounded-lg border p-4 max-w-lg"> <div> <p className="text-2xl font-semibold">4</p> <p className="text-xs text-muted-foreground">Cámaras en línea</p> </div> <div> <p className="text-2xl font-semibold">2</p> <p className="text-xs text-muted-foreground">Movimiento activo</p> </div> <div> <p className="text-2xl font-semibold">12</p> <p className="text-xs text-muted-foreground">Clips hoy</p> </div> <Button size="sm">Abrir vigilancia</Button> </div>
Resumen de API
| Endpoint | Método | Descripción |
|---|---|---|
/api/iot/cctv | GET | Listar cámaras (filtradas por propiedad) |
/api/iot/detection/motion-stream | POST | Iniciar/detener detección de movimiento, configurar opciones |
/api/iot/detection/motion-stream?cctvId=N | GET | Estado y estadísticas de la cámara N |
/api/iot/detection-events | GET | Listar eventos de movimiento con filtros opcionales |
/api/iot/buffer/[cctvId]/clip | GET | Obtener clip del buffer (por rango de tiempo) |
Para formas completas de solicitud/respuesta y webhooks, consulte API REST y Detección de Movimiento.