Componentes Frontend
VideoPlayer Component
Descripción: Componente Vue.js responsable de reproducir video en vivo desde dispositivos DVR utilizando streaming FLV. Maneja todo el ciclo de vida del video desde la solicitud inicial hasta la reproducción y cleanup.
Propiedades (Props)
props: {
series: {
type: String,
description: "Número de serie del DVR"
},
channel: {
type: Number,
description: "Canal de cámara (1-32)"
},
connectionAvailable: {
type: Boolean,
description: "Estado de conectividad del dispositivo"
},
signalStrength: {
type: Number,
default: -1,
description: "Fuerza de señal (0-5, -1 = desconocida)"
},
videoScale: {
type: Boolean,
default: false,
description: "Aplicar escala de video personalizada"
}
}
Estados del Componente (renderState)
- 0: Sin conexión - Muestra ícono de alerta triangular
- 1: Listo para reproducir - Muestra botón de play
- 2: Cargando - Muestra spinner de carga
- 3: Reproduciendo - Video visible sin controles
- 4: Reproduciendo con controles - Video con overlay de controles (hover)
Datos del Componente
data() {
return {
videoElementId: String, // ID único del elemento video
renderState: Number, // Estado actual de renderizado
formattedRemainingTime: String, // Tiempo restante formateado
fullScreen: Boolean, // Estado pantalla completa
destroyed: Boolean, // Flag de componente destruido
session: Object, // Datos de sesión del video
player: Object, // Instancia del reproductor FLV
responseSession: Object, // Respuesta de la sesión
actualResp: Boolean // Flag de respuesta actual
}
}
Computadas
videoResp: Estado del video desde Vuex storeisMobile: Detecta si es dispositivo móvil
Watchers
videoResp
Maneja las respuestas del WebSocket cuando el video está listo.
// Espera 1 segundo para sincronización
await this.sleep(1000);
if (nv.status === 'ready' && nv.sessionId === this.responseSession.sessionId) {
this.playVideo(nv);
}
series
Detecta cambios en el número de serie del DVR y reinicia el componente.
if (newSeries && newSeries !== oldSeries) {
this.videoElementId = newSeries + '-' + this.channel;
this.reset();
}
connectionAvailable & signalStrength
Actualizan el estado visual y muestran alertas de conectividad.
Métodos Principales
onClick() - Inicialización del video
- Establece
renderState = 2(loading) - Marca timestamp de
lastKeepAlive - Detecta tipo de DVR (Aibox, Adplus, M1n)
- Solicita video al backend via
video.requestLiveVideo() - Maneja la respuesta con
handleVideoLiveResponse()
handleVideoLiveResponse(response)
- Valida el estado de respuesta
- Establece
sessionIdystatusde la sesión - Programa timeout de video con
scheduleVideoTimeout() - Implementa fallback de polling si WebSocket falla
playVideo(videoData)
Función core que inicializa el reproductor FLV:
const flvPlayer = flvjs.createPlayer({
type: 'flv',
isLive: true,
hasAudio: false,
hasVideo: true,
url: videoData.streamingUrl,
});
// Eventos críticos
flvPlayer.on(flvjs.Events.ERROR, (error) => {
// NetworkError dispara reset automático
this.reset();
});
flvPlayer.on(flvjs.Events.MEDIA_INFO, () => {
// Video listo, mostrar y iniciar timer
this.renderState = 3;
this.updateVideoTimer();
this.session['interval'] = setInterval(this.updateVideoTimer, 1000);
});
scheduleVideoTimeout()
Gestión de timeout recursiva:
if (this.session.lastKeepAlive) {
const endTime = new Date(
this.session.lastKeepAlive.getTime() + VIDEO_LENGTH * 1000
);
const diffTime = endTime.getTime() - now.getTime();
if (diffTime > 0) {
setTimeout(() => {
this.scheduleVideoTimeout(); // Recursión
}, diffTime);
} else {
this.reset(); // Timeout alcanzado
}
}
updateVideoTimer()
Actualiza cada segundo el tiempo restante y el display:
const elapsed = now - this.session.lastKeepAlive;
const total = VIDEO_LENGTH * 1000; // 120 segundos
this.session.remainingTime = Math.ceil(total - elapsed);
this.session.lowTime = this.session.remainingTime <= 11 * 1000;
onKeepAlive()
Extiende la sesión 30 segundos adicionales:
this.session.lastKeepAlive = new Date(
this.session.lastKeepAlive.getTime() + 30000
);
await video.keepAlive(this.session.sessionId);
reset() - Cleanup completo
- Limpia todos los timers e intervalos
- Destruye el reproductor FLV
- Resetea datos de sesión
- Sale de pantalla completa
- Llama
closeStream()al backend
Funciones de Polling (Fallback WebSocket)
scheduleCheck() & schedulePolling(remainingAttempts)
Sistema de respaldo exponencial cuando WebSocket no responde:
- Calcula tiempo de espera:
2^(maxAttempts - remainingAttempts)segundos - Máximo
Math.ceil(Math.log2(30))intentos - Verifica estado con
video.checkVideo(sessionId)
Funciones de UI
onFullScreen() & exitFullscreen()
Control de pantalla completa con API nativa del navegador.
captureImage()
Captura screenshot del video actual:
- Usa Canvas API para capturar frame
- Aplica factores de escala según tipo de DVR
- Genera descarga automática como JPEG
Ciclo de Vida
mounted()
Configuración inicial de escalado según DVR:
// Escalado específico por tipo de DVR
if (!this.videoScale && this.series.startsWith('009B')) {
video.style.transform = 'scaleX(1.454)';
} else if (this.channel === 9) {
video.style.transform = 'scaleX(1.084)';
} else if (this.videoScale) {
video.style.transform = 'scaleX(1.584)';
}
beforeDestroy()
Cleanup automático al destruir componente:
this.destroyed = true;
this.reset();
Constantes
const VIDEO_CHECK_PERIOD = 30; // Segundos para polling fallback
const VIDEO_LENGTH = 120; // Duración máxima de sesión en segundos
Integración con Backend
WebSocket Events:
videoIsReady(data): Recibe notificación cuando stream está listo
API Calls:
video.requestLiveVideo(): Solicita nueva sesión de videovideo.checkVideo(sessionId): Verifica estado de sesión existentevideo.keepAlive(sessionId): Extiende tiempo de vida de sesiónvideo.closeStream(sessionId): Cierra stream y limpia recursos