Skip to content

Releases: jandersonss/xstream-player

v1.12.0

Choose a tag to compare

@jandersonss jandersonss released this 14 Jul 18:31

Estado do Modo TV em SQLite 📺

O Modo TV guardava as transmissões ativas e o sync de reprodução em dois JSONs (live-sessions.json e live-sync.json), reescritos por inteiro a cada heartbeat e sem nenhum lock. Na prática isso dava dois problemas: dois dispositivos batendo heartbeat ao mesmo tempo liam a mesma lista e um sobrescrevia o outro — o dispositivo sumia da tela do Modo TV até o próximo heartbeat; e, como a escrita não é atômica, quem lesse o arquivo no meio de uma gravação podia pegar um JSON truncado.

Agora esse estado vive em data/tv-mode.sqlite, com upsert por linha e transações: cada heartbeat mexe só na própria linha, e as leituras nunca enxergam um estado pela metade.

Por que um banco separado

Já existiam dois bancos com ciclos de vida opostos — o cache de catálogo (xstream-player.sqlite, descartável) e os dados do usuário (user-data.sqlite, insubstituível). O estado do Modo TV não pertence a nenhum dos dois: ele é efêmero (toda linha expira em segundos sem heartbeat) e recebe escrita o tempo todo. Colocá-lo no banco de usuário incharia justamente o arquivo que importa no backup; colocá-lo no cache faria a limpeza do catálogo — uma operação normal — derrubar transmissões em andamento.

Com um terceiro banco, apagar o tv-mode.sqlite a qualquer momento não custa nada: os dispositivos se re-anunciam no heartbeat seguinte.

O que fazer

Nada. Não há migração: os JSONs antigos são apagados sozinhos na primeira execução, e todo o conteúdo deles expiraria em segundos de qualquer forma. Quem roda várias instâncias compartilhando a pasta data/ continua funcionando igual — o estado compartilhado só mudou de arquivo.

v1.11.1

Choose a tag to compare

@jandersonss jandersonss released this 14 Jul 17:13

Correções na imagem Docker 🐳

Credenciais podiam vazar para dentro da imagem (só em build local)

O file tracing do Next varria a pasta data/ para dentro de .next/standalone, e o estágio final do Dockerfile copia o standalone inteiro. Ou seja: o que estivesse em data/ no momento do build entrava na imagem — inclusive o config.json com as credenciais Xtream em texto puro e o banco de usuário (user-data.sqlite).

Na prática isso só afeta quem builda localmente, numa cópia do projeto que já rodou e portanto tem data/ populado. Um build em pipeline parte de um checkout limpo, sem data/, então não havia o que vazar — nenhuma imagem publicada foi afetada.

A pasta data/ é estado de runtime, montada como volume, e agora está excluída tanto do tracing (next.config.ts) quanto do contexto de build (.dockerignore).

O que fazer: se você construiu a imagem localmente e a compartilhou ou publicou em algum registry, trate as credenciais como expostas e troque a senha do provedor Xtream. Se as imagens locais nunca saíram da sua máquina, basta reconstruir com esta versão.

Script de migração não chegava na imagem

O estágio final também nunca copiava a pasta scripts/, então o comando documentado no próprio script — docker exec <container> node scripts/migrate-subtitles.mjs — falhava com "module not found". Quem atualizou para a v1.11.0 via Docker não conseguiu migrar as legendas antigas para o novo layout por idioma. Agora a pasta é copiada explicitamente.

O que fazer: se você atualizou para a v1.11.0 em Docker e tinha legendas baixadas, rode a migração após subir esta versão:

docker exec <container> node scripts/migrate-subtitles.mjs --dry-run   # confere
docker exec <container> node scripts/migrate-subtitles.mjs             # move

Sem isso, as legendas antigas ficam invisíveis para o player e seriam baixadas de novo, consumindo a cota da OpenSubtitles (5 por dia).

Full Changelog: v1.11.0...v1.11.1

v1.11.0

Choose a tag to compare

@jandersonss jandersonss released this 14 Jul 16:15

Perfis de usuário 👤

Favoritos e "continuar assistindo" eram globais — todas as TVs da casa dividiam a mesma lista. Agora cada pessoa tem o seu perfil, escolhido uma vez por dispositivo.

Novidades

  • Perfis: crie, edite e troque de perfil pelo seletor no topo da sidebar. Favoritos e progresso de reprodução são escopados por perfil; o perfil ativo viaja no cookie xstream_profile, então as rotas resolvem sozinhas quem está assistindo.
  • Dados do usuário em SQLite: perfis, favoritos e progresso saíram dos JSONs e passaram a viver em data/user-data.sqlite, separado do cache de catálogo. Apagar o cache para forçar um re-sync continua sendo uma operação inofensiva — não leva os seus dados junto.
  • Legendas por idioma: o cache de legendas agora é chaveado por idioma (subtitles/<idioma>/). Antes, um download em um idioma sobrescrevia silenciosamente a legenda de outro idioma para o mesmo conteúdo.
  • Busca instantânea: a busca deixou de baixar o catálogo inteiro (20 mil itens, com sinopse, elenco e imagens) para o navegador e filtrar a cada tecla. A consulta vai para o SQLite e volta já ranqueada — e agora ignora acentos e pontuação ("obsessao" acha "Obsessão", "spider man" acha "Spider-Man"). Título exato vem antes de prefixo, que vem antes de palavra, então o filme original fica na frente das continuações.

Interface

  • Sidebar redesenhada no estilo Netflix: compacta, com o perfil no topo.
  • Logo movida para o header da home, com o nome de usuário no badge de status.
  • Badges de conta unificados, mostrando o uso de conexões ao vivo (quantas das suas conexões estão em uso agora).
  • Configurações de legenda saíram da sidebar e foram para o header da home.

Correções

  • TMDb pegava o filme errado: um remake casava com o original ("Obsessão" 2026 → "Obsessão (2019)") e uma sequência casava com a irmã ("Todo Mundo em Pânico 6" → "Todo Mundo em Pânico 2"), o que também fazia as legendas serem baixadas para o filme errado. Ano e número de sequência agora são filtros rígidos, aplicados antes da pontuação de similaridade.
  • Progresso corrompido: o arquivo de resumo era escrito por duas rotas ao mesmo tempo, sem lock nem escrita atômica, e já havia chegado a corromper o watch-progress.json. O resumo agora é derivado das linhas de episódio, não é mais uma segunda cópia mantida à mão.
  • Segredos na resposta da API: as credenciais Xtream deixaram de aparecer na resposta da rota de conta, e passam a ser lidas do formato aninhado do config.

Projeto

  • Licença AGPL-3.0 e CLA para contribuidores, com check de CI que barra PRs sem a frase de aceite. O ffmpeg embutido na imagem Docker (GPL/LGPL) está documentado no README.
  • CLAUDE.md, padrões de projeto e comentários de código traduzidos para inglês (textos de UI seguem em pt-BR).

Atualizando

⚠️ Use a v1.11.1 no lugar desta. Na imagem Docker da v1.11.0 falta a pasta scripts/, então a migração de legendas não roda em container — e um build local (com data/ já populado) embutia o data/config.json na imagem. Build em pipeline, a partir de checkout limpo, não é afetado.

Nada a fazer: favoritos e progresso são importados dos JSONs no primeiro boot e as legendas existentes são movidas por scripts/migrate-subtitles.mjs. O cache do TMDb é invalidado nesta versão (ele guardava os casamentos errados) e será refeito sob demanda.

Full Changelog: v1.10.0...v1.11.0

v1.10.0

Choose a tag to compare

@jandersonss jandersonss released this 13 Jul 15:42

Legendas para séries 🎬

A funcionalidade de legendas (antes exclusiva de filmes) agora funciona para séries.

Novidades

  • Buscar/baixar em lote: fluxo em duas etapas — primeiro buscar (não consome cota) mostra por episódio se há legenda disponível, já baixada ou sem legenda; depois baixar pega apenas as encontradas.
  • Download sob demanda: quando a série já tem legendas, ao abrir um episódio sem legenda ela é buscada e baixada automaticamente antes de reproduzir e anexada ao player — transparente para o usuário.

Correções

  • Detecção correta da cota diária da OpenSubtitles (HTTP 406 com remaining:0 — antes só tratava 407). O lote agora para de forma limpa ao esgotar os 5 downloads/24h e exibe o saldo restante.

Sob o capô

  • Novo endpoint GET /api/subtitles/user/list marca de uma vez os episódios já legendados.
  • Rate limit respeitado com pausa entre requisições e backoff exponencial no servidor.

Full Changelog: v1.9.0...v1.10.0

v1.9.0

Choose a tag to compare

@jandersonss jandersonss released this 13 Jul 15:45

Modo TV — compartilhamento de conexão 📺

Novidades

  • Modo TV: compartilhamento de conexão para transmitir live e VOD via ffmpeg.
  • Transmitir tudo com sincronização entre players, título no player e correção do auto-skip.

Correções

  • Estado de sincronização agora é persistido em data/, funcionando corretamente em cenários multi-instância.

Documentação

  • Documentado o Modo TV (compartilhamento de conexão) e screenshot atualizado.

Full Changelog: v1.8.0...v1.9.0

v1.8.0

Choose a tag to compare

@jandersonss jandersonss released this 13 Jul 15:45

Auto-skip de episódios + otimizações ⏭️

Novidades

  • Pular para o próximo episódio: no último minuto de um episódio de série aparece um prompt com dois botões — pular agora ou adiar (para quando os créditos são curtos e o episódio ainda está rodando). O botão primário em foco avança automaticamente após uma contagem regressiva de 10s.
  • A contagem é ancorada ao tempo do vídeo: congela ao pausar e retrocede ao voltar (seek). A duração é atualizada em durationchange, evitando que streams progressivos disparem o prompt cedo demais.

Performance

  • Menor uso de memória na home em TVs de baixo desempenho.

Sob o capô

  • Migração do armazenamento de cache para SQLite (catálogo, sync do Xtream e sincronização passam pelo fluxo SQLite no servidor).
  • Middleware para redirecionamento de WebOS legado e novas rotas de API.
  • Ajustes de tipagem no acesso a dados de sync e na fachada de cache.

Full Changelog: v1.7.0...v1.8.0

v1.7.0

Choose a tag to compare

@jandersonss jandersonss released this 24 May 22:50

What's Changed

Full Changelog: v1.6.2...v1.7.0

v1.6.2

Choose a tag to compare

@jandersonss jandersonss released this 22 May 22:08

What's Changed

  • Fix WebOS playback loading and add debug diagnostics by @jandersonss in #3

Full Changelog: v1.6.1...v1.6.2

v1.6.1

Choose a tag to compare

@jandersonss jandersonss released this 22 May 17:08

What's Changed

Full Changelog: v1.6.0...v1.6.1

v1.6.0

Choose a tag to compare

@jandersonss jandersonss released this 22 May 16:15

What's Changed

New Contributors

Full Changelog: v1.5.1...v1.6.0