×

📺 IPTV

B2C · Xtream · Reseller

IPTV Gestionar Usuarios

Niveles de almacenamiento de archivo

Sistema de archivo de tres niveles para 500+ clientes concurrentes. Configurar en Config > Almacenamiento > Niveles de almacenamiento. Cada nivel tiene ciclo de vida, cálculo de capacidad y comportamiento de respaldo independientes.

Codificador

Búfer de escritura

Ventana caliente de 2h (NVMe o tmpfs)

→ mirror (continuo)

RAID HDD 5

50 TB, retención de 14 días

→ prefetch bajo demanda

Caché de reproducción

1 TB caché tibia, 500+ clientes

Clientes

Mirror, no mover

Los segmentos más antiguos que mirror_min_age_minutes se COPIAN a RAID continuamente. El write_buffer mantiene una ventana caliente de 2h para que la reproducción de rebobinado reciente se mantenga en almacenamiento rápido. Solo después de evict_age_minutes (y solo cuando se verifica-mirror) se eliminan los segmentos del write_buffer. RAID siempre tiene la copia de cola larga — sin transferencias por ráfaga horarias.

Nivel

Propósito

Configuración

Búfer de escritura

Recibe segmentos 24/7, mantiene una ventana caliente de 2h para reproducción rápida de rebobinado reciente, protege el RAID de E/A aleatoria. El dispositivo puede ser una partición NVMe física (producción) o tmpfs (caja de dev/prueba sin NVMe físico — ver sección tmpfs a continuación).

device_path (dispositivo de bloque o "tmpfs"), tmpfs_size_pct (10-50% MemAvailable cuando tmpfs), mirror_min_age_minutes, evict_age_minutes, flush_threshold_percent (desencadenante de activación de forzado)

Archivo RAID HDD

Almacenamiento de cola larga para retención completa (predeterminado 14 días). Recibe trickle de mirror continuo desde write_buffer — escritura secuencial, sin ráfagas horarias. Sobrevive al reinicio. RAID sobrevive a la falla de un disco.

retention_days, raid_device, nginx_location, min_free_percent

Caché de reproducción (opcional)

Caché de lectura para archivos populares de más de 2h (p. ej., recuperación de EPG). Se llena desde el archivo bajo demanda después del umbral de popularidad (3 clics / 5 min). El dispositivo puede ser NVMe o tmpfs.

prefetch_hours, max_sessions, eviction_policy (session/lru/fifo)

Cálculo de capacidad

escrituras_en_vivo × 2h = tamaño de ventana caliente de write_buffer. Ejemplo: 50 transmisiones × 8 Mbps × 2h ≈ 36 GB. Añadir ~30% de margen para el retroceso de trickle de mirror → ~50 GB de write_buffer es suficiente para 50 transmisiones. RAID dimensionado para retención completa: 50 × 8 Mbps × 14 días ≈ 6 TB.

Lecturas (búsqueda consciente del nivel)

Stream.dvr_file_path/2 sondea write_buffer → playback_cache → archive en orden. Un segmento en la ventana caliente de 2h se sirve desde write_buffer a velocidades nativas aunque también existe en RAID. Nginx X-Accel-Redirect sirve archivos directamente sin pasar por Phoenix.

Disco virtual tmpfs (dev/prueba)

Cada nivel puede usar un disco virtual tmpfs respaldado por RAM en lugar de un dispositivo de bloque físico. Útil para cajas de dev sin NVMe libre, o para entornos de prueba efímeros. El selector desplegable del dispositivo de la tarjeta de Nivel de almacenamiento contiene una opción "tmpfs (disco virtual desde RAM)" que reemplaza el selector de ruta del dispositivo con un control deslizante de porcentaje.

Tamaño en % de RAM libre

La asignación se especifica como un porcentaje de MemAvailable (de /proc/meminfo) — paso 10, valores válidos 10/20/30/40/50. Piso duro 10% (la validación rechaza por debajo). Techo duro 50%. Predeterminado 30%. En un host de 100 GB de MemAvailable: 10% = 10 GB, 30% = 30 GB, 50% = 50 GB. El tamaño se vuelve a calcular y se vuelve a montar en vivo cuando se mueve el control deslizante y se guarda.

Guardia de seguridad contra OOM

Si el objetivo calculado excedería el 60% de MemAvailable actual, el montaje se rechaza y el nivel se mantiene sin conexión (Stream.archive_path se deriva al siguiente nivel saludable). Evita que una configuración agresiva mate a BEAM por OOM. El control se ejecuta tanto al arranque como en cada Guardado en la IU.

Persistencia al reinicio

tmpfs vive en RAM — todo el contenido del búfer en tránsito se PIERDE cuando el host se reinicia. La entrada fstab escrita en el momento del aprovisionamiento vuelve a montar el tmpfs vacío automáticamente al siguiente arranque, pero los segmentos antiguos no regresan. El mirror al archivo continúa normalmente para todo lo que ya fue mirror antes del reinicio — solo la última ventana sin mirror (típicamente < mirror_min_age_minutes) se pierde. Para producción, usar un dispositivo NVMe físico; tmpfs está diseñado como sustituto de dev/prueba.

Cuándo usar tmpfs

Usar tmpfs para write_buffer cuando: (a) caja de dev/prueba no tiene NVMe libre pero aún se quiere la canalización DVR completa funcionando para pruebas de integración, (b) el operador quiere validar el comportamiento de mirror + archivo sin comprar NVMe por adelantado, (c) pruebas efímeras donde la pérdida_al_reinicio es aceptable. NO usar tmpfs en producción — la RAM es volátil y órdenes de magnitud más cara que NVMe por GB de retención.

Flushing más rápido para tmpfs

Cuando el nivel de escritura es tmpfs, StorageTierFlush usa valores predeterminados más ajustados — mirror_min_age 2 min, evict_age 15 min (vs 5 min / 120 min para NVMe físico). La RAM es más cara que el disco, por lo que la ventana caliente de rodillo se mantiene más pequeña. Sobrescribir mediante variables de entorno MIRROR_MIN_AGE_MINUTES / EVICT_AGE_MINUTES si es necesario.

Provisión automática de niveles y seguridad

Los niveles se configuran una vez a través de Config > Almacenamiento > Niveles de almacenamiento y se aprovisionan automáticamente — sin edición manual de mkfs/mount/fstab en el host. StorageTier.ensure_all_provisioned/0 se ejecuta en cada arranque desde SystemInitializer y es idempotente: los niveles ya montados se omiten, los dispositivos faltantes son no-ops, los niveles tmpfs se vuelven a montar limpiamente después del reinicio.

Semilla de arranque predeterminada

Al primer arranque (sin nivel de escritura en la BD), el sistema crea automáticamente un nivel de escritura respaldado por tmpfs con una asignación del 30% de MemAvailable, punto de montaje /mnt/nvme_write. Esto proporciona una canalización DVR funcional desde el primer momento en cualquier host con suficiente RAM. El operador puede cambiar posteriormente el dispositivo a un NVMe físico a través de la IU sin perder otra configuración de nivel.

Salud y conmutación por error

Stream.archive_path/1 devuelve el primer nivel "saludable" — write_buffer si está montado+escriturable+free_pct por encima del piso de seguridad, de lo contrario se reduce a archivo (modo degradado). Piso de seguridad del 20% para tmpfs (RAM-estricto), 2% para dispositivos de bloque. El punto final tier_health expone mounted/escriturable/free_pct por nivel para monitoreo.

Cambio de tamaño en vivo

Cambiar tmpfs_size_pct en la IU desencadena umount + remount con el nuevo tamaño en Guardar. Las escrituras DVR activas se pausan brevemente (transición de montaje < 1 s). Recomendación: cambiar el tamaño de tmpfs solo cuando la tasa de escritura DVR sea baja, y considerar reiniciar las transmisiones después para asegurar que recojan el nuevo montaje limpiamente.

URL base — OSTV Player

Campos del paquete

API de paquetes

Política de contraseñas

API de revendedores

Configuración

Campos de usuario

Gestión de usuarios

IPTV Gestionar Usuarios

URL base — Reproductor OSTV

La aplicación OSTV Player permite a los usuarios cambiar la URL base del servidor (dirección de API). Esta función solo está disponible para usuarios con proveedor configurado como root.

Motivo: cambiar la URL base está pensado únicamente para administradores/usuarios root para que puedan alternar entre servidores (p. ej. producción vs. pruebas). Los usuarios normales tienen una URL base fija y no pueden cambiarla.

Campos de usuario

API de paquetes

Devuelve la lista de todos los paquetes activos con precios y períodos de facturación.

Lista de usuarios de gestión (revendedores / proveedores).

Devuelve el saldo de crédito de un usuario de gestión específico.

Campos del paquete

API de revendedor

API para revendedores/proveedores. Autorización: Authorization: Bearer mtk_... (token de Manage Users). El revendedor solo ve a sus propios clientes (owner_id).

Política de contraseñas

La contraseña es obligatoria al crear un suscriptor. Reglas:

Mínimo 8 caracteres

Al menos 1 letra mayúscula (A-Z)

Al menos 1 carácter especial (!@#$%^&* etc.)

Se aplica a la UI y a la API. En la actualización, la contraseña es opcional, pero si se proporciona debe cumplir las reglas.

Configuración

Aprovisionamiento automático de nivel y seguridad

Detección automática de capacidad y sistema de archivos: cuando se selecciona una NVMe libre en el desplegable, la capacidad (GB) se lee desde lsblk -bn -o SIZE y el FS actual desde blkid (con reserva de disco completo). El formulario muestra los valores de solo lectura — sin entrada manual, sin errores.

Mecanismo de vaciado de nivel — Espejo continuo

StorageTierFlush GenServer se ejecuta cada 60 s. En lugar de esperar a que un directorio de hora «envejezca» y moverlo como ráfaga de 5 GB, transfiere segmentos al RAID de forma continua manteniendo una ventana activa de 2 h en NVMe para reproducción rápida «rebobinado reciente». Las dos fases están desacopladas: copiar y eliminar son operaciones separadas y verificadas.

Por qué el espejo continuo supera al «esperar 60 min, mover en lote»: (1) La carga del RAID es uniforme — sin ráfagas de 5 GB en los límites de hora, solo flujo continuo de segmentos de 7 MB; (2) La mayoría de los datos activos ya están en RAID — la recuperación ante desastres solo pierde los últimos minutos; (3) La eliminación se verifica por archivo — un fallo parcial del espejo se detecta antes de que se pierda ningún dato de NVMe.

Seguridad de segmentos en proceso: el espejo solo selecciona archivos más antiguos que MIRROR_MIN_AGE_MINUTES mediante find -mmin +5. Un archivo de segmento que todavía está siendo escrito por FFmpeg no aparecerá en la lista — ninguna posibilidad de transferencia de escritura parcial.

Ajuste por despliegue (.env)

500–1000

Regla de dimensionamiento:

Calendario de vista previa DVR

La pestaña Vista previa DVR muestra un calendario renderizado en el servidor que resalta solo los días para los que existen grabaciones en disco. El análisis se ejecuta en todos los niveles (write_buffer + read_cache + archive + legacy) para que un segmento recién transferido de NVMe a RAID siga visible sin demora.

Los días con grabaciones son clicables (azul) — al hacer clic se rellena previamente la entrada de fecha y hora con ese día a las 00:00; el usuario luego elige la hora. Los días sin grabación aparecen atenuados e inactivos.

Implementado en Stream.available_dvr_days/1 mediante find -mindepth 4 -maxdepth 4 -type d en cada punto de montaje de nivel; deduplicado entre niveles (un día se muestra una sola vez aunque tenga segmentos en varios niveles durante una ventana de transferencia).

API de reproductor B2C

Descripción general

La API B2C (Business-to-Consumer) proporciona autenticación y acceso a transmisiones para aplicaciones de reproductores de usuarios finales. Los usuarios se autentican con nombre de usuario/contraseña y reciben un token auth por tiempo limitado para solicitudes posteriores.

Autenticación

Autenticar un usuario y obtener un auth_token para llamadas API posteriores.

Método

Punto final

Cuerpo de la solicitud

Parámetro

Tipo

Obligatorio

Descripción

Nombre de inicio de sesión del usuario

Contraseña del usuario

Solicitud de ejemplo

Campos de respuesta

Respuesta exitosa (200)

Token de autenticación encriptado para llamadas API posteriores

Fecha/hora de expiración del token en formato ISO 8601

Respuesta exitosa de ejemplo

Respuesta de error (403)

Mensaje de descripción del error

Código de estado HTTP

Respuesta de error de ejemplo

Información del usuario

Recuperar información sobre el usuario autenticado usando el token auth.

Campos de respuesta

Nombre de usuario del usuario autenticado

Mensaje del servidor (vacío si none)

Estado de autenticación (1 = autenticado)

Estado de la cuenta: Active, Banned, Disabled, Trial

Fecha de expiración de la cuenta (null si es ilimitada)

Número de conexiones activas actuales

Fecha de creación de cuenta en formato ISO 8601

Conexiones simultáneas máximas permitidas

Lista de formatos de transmisión de salida permitidos

Nombre del proveedor del propietario/revendedor del usuario (null si none)

URL de la imagen de logotipo del proveedor (null si none)

URL de la imagen de logotipo de colapso del proveedor 208x208 (null si none)

Hora actual del servidor en formato ISO 8601

Solicitud de ejemplo

Categorías

Recuperar categorías filtradas por tipo. Tipos disponibles: live (transmisiones), vod (películas), series.

Tipo de categoría: live, vod o series

ID de categoría como cadena

Nombre de visualización de categoría

ID de categoría padre (0 si es raíz)

Hash MD5 del contenido para invalidación de caché

Solicitud de ejemplo

Detalle de VOD

Recuperar información detallada para un elemento VOD específico, incluyendo metadatos y enlaces de transmisión.

ID de transmisión VOD (UUID)

Campos del objeto Info

URL de imagen de portada

Identificador TMDB

URL de imagen de fondo

Género como cadena

Trama/descripción

Miembros del elenco

Valor de calificación (0-10)

Nombre del director

Fecha de lanzamiento

Duración en segundos

Duración como cadena formateada

Array de IDs de categoría

1 si es contenido para adultos, 0 en caso contrario

Campos del objeto VOD

ID de transmisión VOD

Título de VOD

Fecha de adición (ISO 8601)

URLs de enlace de transmisión

Metadatos de códec de video/audio

Detalle de la serie

Recuperar información de la serie con listados completos de temporadas y episodios, agrupados por número de temporada.

ID de serie (UUID)

Campos del array de temporadas

Número de temporada

Nombre de visualización de temporada

Número de episodios en la temporada

Fecha de emisión de la temporada

Resumen/descripción de la temporada

URL de imagen de portada de temporada

Objeto de episodios

Mapa indexado por cadena de número de temporada. Cada valor es un array de objetos episodio.

Campos del objeto episodio

ID del episodio

ID de episodio TMDB

Número de episodio dentro de la temporada

Título del episodio

Fecha de adición (ISO 8601)

Número de temporada

Objeto de info de episodio (misma estructura que info de VOD)

URLs de enlace de transmisión

Metadatos de códec de video/audio

Notas

La expiración del token depende del rol del usuario: admin = 365 días, otros = 30 días|Las cuentas deshabilitadas no pueden autenticarse (devuelve 403)|Cada inicio de sesión actualiza el timestamp last_login del usuario|Los tokens están encriptados y contienen user_id, username, role y expiration

Respuesta exitosa (200)

Token auth obtenido del punto final /auth