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