B2C · Xtream · Reseller





Camadas de Armazenamento de Arquivo
Sistema de arquivo em três camadas para 500+ clientes simultâneos. Configure em Config > Armazenamento > Camadas de Armazenamento. Cada camada tem ciclo de vida, cálculo de capacidade e comportamento de fallback independentes.
Codificador
Buffer de Escrita
Janela quente de 2h (NVMe ou tmpfs)
→ espelhar (contínuo)
HDD RAID 5
50 TB, retenção de 14 dias
→ pré-buscar sob demanda
Cache de Reprodução
1 TB de cache quente, 500+ clientes
Clientes
Segmentos mais antigos que mirror_min_age_minutes são COPIADOS para o RAID continuamente. O write_buffer mantém uma janela quente rolante de 2h para que a reprodução de retrocesso (rewind) recente permaneça no armazenamento rápido. Apenas após evict_age_minutes (e apenas quando verificado como espelhado) os segmentos são excluídos do write_buffer. O RAID sempre tem a cópia de cauda longa — sem transferências em rajada horária.
Camada
Finalidade
Configurações
Buffer de Gravação
Recebe segmentos 24/7, mantém uma janela quente de 2h para reprodução rápida de retrocesso recente, protege o RAID contra E/S aleatórias. O dispositivo pode ser uma partição NVMe física (produção) ou tmpfs (caixa de dev/teste sem NVMe físico — veja a seção tmpfs abaixo).
device_path (dispositivo de bloco ou 'tmpfs'), tmpfs_size_pct (10-50% de MemAvailable quando tmpfs), mirror_min_age_minutes, evict_age_minutes, flush_threshold_percent (gatilho de forçar flush)
Arquivo HDD RAID
Armazenamento de longo prazo para retenção completa (padrão 14 dias). Recebe um espelhamento contínuo e gradual do write_buffer — gravação sequencial, sem picos horários. Sobrevive a reinicializações. O RAID sobrevive à falha de um único disco.
retention_days, raid_device, nginx_location, min_free_percent
Cache de Reprodução (opcional)
Cache de leitura para arquivos populares com mais de 2h (ex.: catch-up de EPG). Preenchido a partir do archive sob demanda após o limite de popularidade (3 acessos / 5 min). O dispositivo pode ser NVMe ou tmpfs.
prefetch_hours, max_sessions, eviction_policy (session/lru/fifo)
live writes × 2h = tamanho da janela quente do write_buffer. Exemplo: 50 streams × 8 Mbps × 2h ≈ 36 GB. Adicione ~30% de margem para backlog do trickle de espelhamento → ~50 GB de write_buffer são suficientes para 50 streams. RAID dimensionado para retenção completa: 50 × 8 Mbps × 14 dias ≈ 6 TB.
Stream.dvr_file_path/2 verifica write_buffer → playback_cache → archive na ordem. Um segmento na janela quente de 2h é servido do write_buffer em velocidades nativas, mesmo que também exista no RAID. O Nginx X-Accel-Redirect serve arquivos diretamente sem passar pelo Phoenix.
Cada camada pode usar um disco virtual tmpfs baseado em RAM em vez de um dispositivo de bloco físico. Útil para caixas de desenvolvimento sem NVMe sobressalente, ou para ambientes de teste efêmeros. A lista suspensa de dispositivos do cartão Storage Tier contém uma opção 'tmpfs (disco virtual da RAM)' que substitui o seletor de caminho do dispositivo por um controle deslizante de porcentagem.
A alocação é especificada como uma porcentagem do MemAvailable (de /proc/meminfo) — passo 10, valores válidos 10/20/30/40/50. Piso rígido de 10% (a validação rejeita valores abaixo). Teto rígido de 50%. Padrão 30%. Em um host com 100 GB de MemAvailable: 10% = 10 GB, 30% = 30 GB, 50% = 50 GB. O tamanho é recalculado e remontado em tempo real quando o controle deslizante é movido e salvo.
Se o alvo calculado exceder 60% do MemAvailable atual, a montagem é recusada e a camada permanece offline (Stream.archive_path passa para a próxima camada saudável). Impede que uma configuração agressiva derrube o BEAM via OOM. O guarda-execução é executado tanto na inicialização quanto em cada Salvamento na interface.
O tmpfs vive na RAM — qualquer conteúdo de buffer em trânsito é PERDIDO quando o host reinicia. A entrada fstab escrita no momento do provisionamento monta novamente o tmpfs vazio automaticamente na próxima inicialização, mas os segmentos antigos não retornam. O espelhamento para o archive continua normalmente para tudo que já foi espelhado antes da reinicialização — apenas a última janela não espelhada (tipicamente < mirror_min_age_minutes) é perdida. Para produção, use um dispositivo NVMe físico; o tmpfs destina-se como substituto para dev/teste.
Use tmpfs para write_buffer quando: (a) a caixa de dev/teste não tiver NVMe sobressalente, mas você ainda quiser o pipeline DVR completo em execução para testes de integração, (b) o operador quiser validar o comportamento de espelhamento + archive sem comprar NVMe antecipadamente, (c) testes efêmeros onde a perda na reinicialização é aceitável. NÃO use tmpfs em produção — a RAM é volátil e ordens de magnitude mais cara que NVMe por GB de retenção.
Quando a camada de gravação é tmpfs, o StorageTierFlush usa padrões mais rigorosos — mirror_min_age 2 min, evict_age 15 min (vs 5 min / 120 min para NVMe físico). A RAM é mais cara que o disco, por isso a janela quente rolante é mantida menor. Substitua via variáveis de ambiente MIRROR_MIN_AGE_MINUTES / EVICT_AGE_MINUTES se necessário.
As camadas são configuradas uma vez via Config > Armazenamento > Camadas de Armazenamento e provisionadas automaticamente — sem edição manual de mkfs/mount/fstab no host. StorageTier.ensure_all_provisioned/0 é executado em cada inicialização a partir do SystemInitializer e é idempotente: camadas já montadas são ignoradas, dispositivos ausentes são ignorados, camadas tmpfs são remontadas limpas após a reinicialização.
Na primeira inicialização (sem camada de escrita no DB), o sistema cria automaticamente uma camada de escrita baseada em tmpfs com alocação de 30% do MemAvailable, ponto de montagem /mnt/nvme_write. Isso fornece um pipeline DVR funcional imediatamente em qualquer host com RAM suficiente. O operador pode posteriormente alterar o dispositivo para um NVMe físico via UI sem perder as configurações de outras camadas.
Stream.archive_path/1 retorna a primeira camada 'saudável' — write_buffer se montado+gravação+free_pct acima do piso de segurança, caso contrário, falha para o archive (modo degradado). Piso de segurança de 20% para tmpfs (RAM-estricto), 2% para dispositivos de bloco. O endpoint tier_health expõe por camada: mounted/gravação/free_pct para monitoramento.
Alterar tmpfs_size_pct na UI aciona um desmonte + remonte com o novo tamanho ao salvar. As gravações DVR ativas são brevemente pausadas (transição de montagem < 1 s). Recomendação: altere o tamanho do tmpfs apenas quando a taxa de gravação do DVR for baixa e considere reiniciar os streams para garantir que eles peguem a nova montagem limpa.
URL Base — OSTV Player
Campos do Pacote
API de Pacotes
Política de Senha
API de Revendedor
Configurações
Campos do Usuário
Gerenciamento de Usuários
URL Base — Player OSTV
A aplicação OSTV Player permite aos utilizadores alterar o URL base do servidor (endereço de API). Esta funcionalidade está disponível apenas para utilizadores com provider definido como root.
Motivo: Alterar o URL base destina-se apenas a administradores/utilizadores root para que possam alternar entre servidores (ex. produção vs. teste). Os utilizadores regulares têm um URL base fixo.
Campos do Utilizador
API de Pacotes
Retorna uma lista de todos os pacotes ativos com preços e períodos de faturação.
Lista de utilizadores de gestão (revendedores / fornecedores).
Retorna o saldo de crédito para um utilizador de gestão específico.
Campos de Pacote
API de Revendedor
API para revendedores/fornecedores. Autorização: Authorization: Bearer mtk_... (token de Gerir Utilizadores). O revendedor vê apenas os seus próprios clientes (owner_id).
Política de Palavras-passe
A palavra-passe é obrigatória ao criar um subscritor. Regras:
Mínimo 8 caracteres
Pelo menos 1 letra maiúscula (A-Z)
Pelo menos 1 carácter especial (!@#$%^&* etc.)
Aplica-se à UI e à API. Na atualização, a palavra-passe é opcional, mas se fornecida deve cumprir as regras.
Definições
Auto-Provisionamento de Tier & Segurança
Auto-deteção de capacidade + sistema de ficheiros: quando um NVMe livre é selecionado no dropdown, a capacidade (GB) é lida de lsblk -bn -o SIZE e o FS atual de blkid. O formulário mostra os valores em modo só leitura.
Mecanismo de Flush de Tier — Mirror Contínuo
O GenServer StorageTierFlush executa a cada 60s. Em vez de esperar que um diretório de hora envelheça e mover 5GB de uma vez, transfere segmentos continuamente para RAID mantendo uma janela quente de 2h em NVMe para reprodução rápida. As duas fases são desacopladas — cópia e eliminação são operações separadas e verificadas.
Por que o mirror contínuo é melhor que esperar 60min e mover em lote: (1) Carga RAID uniforme — sem picos de 5GB nos limites de hora; (2) A maioria dos dados quentes já está em RAID — recuperação de desastre perde apenas os últimos minutos; (3) A expulsão é verificada por ficheiro.
Segurança de segmento em progresso: o mirror apenas seleciona ficheiros mais antigos que MIRROR_MIN_AGE_MINUTES via find -mmin +5. Um ficheiro ainda a ser escrito pelo FFmpeg não aparecerá na lista.
Ajuste por Deployment (.env)
500–1000
Regra de dimensionamento:
Calendário de Pré-visualização DVR
O separador de Pré-visualização DVR mostra um calendário renderizado pelo servidor que destaca apenas os dias com gravações em disco. A verificação percorre todos os tiers para que um segmento recentemente transferido de NVMe para RAID fique visível sem demora.
Os dias com gravações são clicáveis (azul) — clicar pré-preenche o campo de data/hora com esse dia às 00:00. Os dias sem gravação estão acinzentados e inativos.
Implementado em Stream.available_dvr_days/1 via find -mindepth 4 -maxdepth 4 -type d em cada ponto de montagem de tier; desduplicado entre tiers.
Visão Geral
A API B2C (Business-to-Consumer) fornece autenticação e acesso ao stream para aplicativos de player de usuário final. Os usuários se autenticam com nome de usuário e senha e recebem um token de autenticação com tempo limitado para solicitações subsequentes.
Autenticar um usuário e obter um auth_token para chamadas subsequentes à API.
Método
Endpoint
Corpo da Solicitação
Parâmetro
Tipo
Obrigatório
Descrição
Sim
Nome de login do usuário
Senha do usuário
Exemplo de Solicitação
Campos da Resposta
Resposta de Sucesso (200)
Token de autenticação criptografado para chamadas subsequentes à API
Data/hora de expiração do token no formato ISO 8601
Exemplo de Resposta de Sucesso
Resposta de Erro (403)
Mensagem de descrição do erro
Código de status HTTP
Exemplo de Resposta de Erro
Recupera informações sobre o usuário autenticado usando o token de autenticação.
Campos de Resposta
Nome de usuário do usuário autenticado
Mensagem do servidor (vazio se não houver)
Status de autenticação (1 = autenticado)
Status da conta: Ativo, Banido, Desativado, Teste
Data de expiração da conta (nulo se ilimitado)
Número de conexões ativas atuais
Data de criação da conta no formato ISO 8601
Número máximo de conexões simultâneas permitidas
Lista de formatos de stream de saída permitidos
Nome do provedor do proprietário/revendedor do usuário (nulo se não houver)
URL da imagem do logotipo do provedor (nulo se não houver)
URL da imagem do logotipo de colapso do provedor 208x208 (nulo se não houver)
Hora atual do servidor no formato ISO 8601
Exemplo de Solicitação
Recuperar categorias filtradas por tipo. Tipos disponíveis: live (streams), vod (filmes), series (séries).
Tipo de categoria: live, vod ou series
ID da categoria como string
Nome de exibição da categoria
ID da categoria pai (0 se for raiz)
Hash MD5 do conteúdo para invalidação de cache
Exemplo de Solicitação
Recupera informações detalhadas sobre um item VOD específico, incluindo metadados e links de stream.
ID do stream VOD (UUID)
URL da imagem de capa
Identificador TMDB
URL da imagem de fundo
String de gênero
Enredo / descrição
Elenco
Valor da classificação (0-10)
Nome do diretor
Data de lançamento
Duração em segundos
Duração como string formatada
Array de IDs de categoria
1 se for conteúdo adulto, 0 caso contrário
ID do stream VOD
Título do VOD
Data de adição (ISO 8601)
URLs de links de streaming
Metadados de codec de vídeo/áudio
Recuperar informações da série com listagens completas de temporadas e episódios, agrupadas por número da temporada.
ID da Série (UUID)
Número da temporada
Nome de exibição da temporada
Número de episódios na temporada
Data de estreia da temporada
Visão geral / descrição da temporada
URL da imagem de capa da temporada
Mapa com chave como string do número da temporada. Cada valor é um array de objetos de episódio.
Campos do Objeto de Episódio
ID do Episódio
ID do episódio no TMDB
Número do episódio dentro da temporada
Data de adição (ISO 8601)
Número da temporada
Objeto de informações do episódio (mesma estrutura que as informações de VOD)
URLs dos links de stream
Metadados de codec de vídeo/áudio
A expiração do token depende do papel do usuário: admin = 365 dias, outros = 30 dias|Contas desabilitadas não podem autenticar (retorna 403)|Cada login bem-sucedido atualiza o timestamp last_login do usuário|Os tokens são criptografados e contêm user_id, username, role e expiration
Resposta de Sucesso (200)
Token de autenticação obtido do endpoint /auth