B2C · Xtream · Reseller





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
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)
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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).
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.
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
Sí
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
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
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
Recuperar información detallada para un elemento VOD específico, incluyendo metadatos y enlaces de transmisión.
ID de transmisión VOD (UUID)
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
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
Recuperar información de la serie con listados completos de temporadas y episodios, agrupados por número de temporada.
ID de serie (UUID)
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
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
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
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