Saltar al contenido principal

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 store
  • isMobile: 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​

  1. Establece renderState = 2 (loading)
  2. Marca timestamp de lastKeepAlive
  3. Detecta tipo de DVR (Aibox, Adplus, M1n)
  4. Solicita video al backend via video.requestLiveVideo()
  5. Maneja la respuesta con handleVideoLiveResponse()

handleVideoLiveResponse(response)​

  1. Valida el estado de respuesta
  2. Establece sessionId y status de la sesión
  3. Programa timeout de video con scheduleVideoTimeout()
  4. 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​

  1. Limpia todos los timers e intervalos
  2. Destruye el reproductor FLV
  3. Resetea datos de sesión
  4. Sale de pantalla completa
  5. 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:

  1. Usa Canvas API para capturar frame
  2. Aplica factores de escala según tipo de DVR
  3. 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 video
  • video.checkVideo(sessionId): Verifica estado de sesión existente
  • video.keepAlive(sessionId): Extiende tiempo de vida de sesión
  • video.closeStream(sessionId): Cierra stream y limpia recursos