# ArkVideo VSL para cPanel — painel + player + upload MP4

Este pacote executa o painel e o player público no seu cPanel com Node.js. **Os arquivos enviados ficam no disco do cPanel, nunca na Teable.** Os registros, métricas e a autenticação continuam na Teable. Não é uma edição independente da Teable e não contém banco MySQL nem sistema próprio de senhas.

O pacote não altera os apps Teable existentes, não publica nada automaticamente e não contém vídeos, exemplos de registros, credenciais reais ou tokens de acesso.

## Antes de instalar: requisitos que precisam ser atendidos

1. cPanel com Setup Node.js App / Configurar aplicativo Node.js e Passenger. Use **Node.js 22 LTS** (mínimo 20.9).
2. Domínio ou subdomínio real com HTTPS. Instale na raiz do domínio/subdomínio, não em `/uma-subpasta`.
3. Terminal do cPanel ou SSH da sua própria conta. Não precisa de root. A hospedagem precisa permitir dependências Node.js, build Next.js, conexões HTTPS de saída para a Teable e escrita em disco.
4. Espaço para código, dependências, build e vídeos. O limite padrão por vídeo é 2 GiB; a quota e a banda do seu plano continuam valendo. O build pode precisar de mais memória do que planos pequenos oferecem.
5. **Credencial de runtime autorizada da aplicação Teable original.** As variáveis `TEABLE_API_URL`, `TEABLE_APP_TOKEN`, `TEABLE_APP_ID` e `TEABLE_BASE_ID` precisam ser configuradas privadamente no cPanel. Elas não são exportadas no ZIP. Um token pessoal genérico não deve ser tratado como equivalente ao token de runtime: o login nativo e a assinatura da sessão dependem dessa credencial.
6. **Para Google: publique o app ArkVideo VSL na Teable, por uma ação sua**, mantendo Google + email OTP e acesso `existing-only`. O fluxo usa a janela/popup e o relay nativos; o retorno OAuth continua no app Teable publicado. Esta edição não registra um cliente OAuth próprio do Google. Não configure um callback do cPanel no Google como se fosse uma nova integração.

### Limite importante de portabilidade do App Login

O código nativo chama a API privada de autenticação da Teable. Não encontramos documentação de um produto App Login self-hosted ou de emissão de tokens de runtime para instalações externas. Portanto, **a disponibilidade dessa credencial e a aceitação do uso externo precisam ser confirmadas na sua conta/com o suporte Teable**. Se a plataforma não disponibilizar esse acesso, o pacote não consegue autenticar nem acessar as tabelas só com os arquivos do ZIP. Não desative o login e não exponha um token para contornar isso. Seria necessária uma decisão separada para migrar banco/autenticação.

A integração real no seu domínio e a conclusão do Google pela sua conta não podem ser verificadas antes dessa configuração. O build e os testes locais não substituem essa etapa.

## 1. Preparar os diretórios

No Gerenciador de Arquivos, crie dois diretórios privados na sua conta:

- Um para o código do app, fora de `public_html`.
- Outro persistente para os vídeos, também fora de `public_html` e fora de `public`/`.next` do app.

Extraia o ZIP no diretório do app. `package.json`, `app.cjs` e este guia devem estar diretamente na raiz escolhida. Não envie `node_modules` de outro computador nem arquivos `.env` da Teable.

O diretório de vídeos será configurado em `ARKVIDEO_MEDIA_DIR`, com o caminho absoluto mostrado pelo seu cPanel. O app cria `uploads/` para partes temporárias e `files/` para MP4 concluídos. Os arquivos serão servidos com segurança pela rota `/media/{UUID}.mp4`.

## 2. Criar o aplicativo no cPanel

No Setup Node.js App:

| Campo | Valor |
|---|---|
| Node.js version | 22 LTS, ou versão compatível >=20.9 |
| Application mode | Production |
| Application root | Diretório privado em que você extraiu o código |
| Application URL | Seu domínio/subdomínio com HTTPS, na raiz |
| Application startup file | `app.cjs` |

O Passenger escolhe o socket. Não é necessário abrir porta, usar root, PM2 ou iniciar `next dev`. Se a hospedagem só aceitar startup com extensão `.js`, copie `app.cjs` para `app.js` e indique `app.js`; o conteúdo continua CommonJS.

Use uma única instância do app neste primeiro pacote. A telemetria herdada do player serializa eventos por processo; não habilite escalabilidade com múltiplos workers sem coordenação compartilhada/CAS. Se o plano iniciar várias instâncias automaticamente, peça à hospedagem que limite esta aplicação a uma antes de ativar métricas de produção.

## 3. Configurar as variáveis

Use a seção Environment variables do cPanel. Alternativamente, copie `.env.example` para `.env.production` no diretório privado do app. Nunca coloque esse arquivo em `public_html`.

| Variável | Configuração |
|---|---|
| `NODE_ENV` | `production` |
| `CPANEL_PUBLIC_ORIGIN` | Origem HTTPS real do domínio cPanel, sem caminhos, query strings ou credenciais |
| `TEABLE_API_URL` | Origem real da API Teable autorizada para a conta |
| `TEABLE_APP_TOKEN` | Credencial de runtime autorizada do app ArkVideo VSL; não vem no pacote |
| `TEABLE_APP_ID` | `appriPxXKrVrdZnChTa` |
| `TEABLE_BASE_ID` | `bseOeAxH4J1cOlemT2F` |
| `ARKVIDEO_MEDIA_DIR` | Caminho absoluto do diretório persistente de vídeos |
| `ARKVIDEO_MAX_UPLOAD_MB` | `2048` inicialmente; aumente conforme quota e recursos reais do plano |

Os provedores de login são fixados em `email-otp,google` na configuração de build; não existe modo público para o painel.

## 4. Instalar e compilar

Ative o ambiente Node.js usando **o comando mostrado pelo próprio Setup Node.js App**. Em seguida, entre no diretório do app.

Se `pnpm` já estiver disponível:

```sh
pnpm install --prod=false
pnpm check:config
pnpm typecheck
pnpm build
```

Se não estiver disponível, use o Corepack fornecido pelo Node, quando a hospedagem permitir:

```sh
corepack pnpm install --prod=false
corepack pnpm check:config
corepack pnpm typecheck
corepack pnpm build
```

Se não houver pnpm/Corepack, peça à hospedagem para habilitar pnpm para sua conta. Não é necessário instalá-lo como root. O projeto fixa pnpm 9.15.9. O arquivo `.npmrc` usa dependências hoisted para facilitar o ambiente Node do cPanel.

`check:config` confere formato das variáveis e permissões locais. Não revela valores secretos e não certifica que a Teable autorizou execução externa. O build utiliza a configuração normal do Next.js, sem `output: standalone`, pois `app.cjs` é um servidor customizado para Passenger.

Clique em **Restart** no cPanel. Atualizações posteriores também exigem `pnpm build` e reinício. Não use o botão de instalar dependências baseado em outro gerenciador para misturar lockfiles.

## 5. Entrar e cadastrar o primeiro vídeo

1. Abra o domínio real do cPanel. O painel redireciona para `/login`.
2. Entre com Google ou código por e-mail usando uma conta cadastrada em **Acessos ArkVideo**.
3. Clique em **Novo vídeo**. Na aba **Vídeo**, use **Enviar MP4 para o cPanel**.
4. Selecione o MP4 e clique em **Enviar arquivo**. O envio ocorre em partes de 4 MiB, com progresso e reenvio de partes em caso de falha.
5. Ao terminar, o link HTTPS local é preenchido automaticamente. Clique em **Testar reprodução** para verificar codec, imagem/som e capturar a duração.
6. Personalize capa, marca, cor, autoplay, retomada, CTA e domínios. Salve o cadastro e ative o vídeo quando estiver pronto.
7. Em **Como incorporar**, salve a **mesma origem HTTPS real do cPanel**. O embed será `/embed/{Identificador público}` nesse domínio.

A configuração de origem usa o mesmo registro Configurações ArkVideo dos apps Teable. Alterá-la pelo cPanel também muda a origem indicada no painel Teable. Isso é intencional para usar o cPanel como player principal.

### Uploads e interrupções

- Upload local é **MP4**. HLS continua disponível por URL externa direta; o pacote não recebe pastas HLS nem faz transcodificação.
- A extensão e o cabeçalho MP4 são verificados; a compatibilidade do codec deve ser confirmada no teste real. O app não converte arquivos automaticamente.
- **Pausar após esta parte** preserva o progresso. **Continuar envio** funciona enquanto a mesma janela e o arquivo selecionado permanecem abertos.
- Fechar/recarregar a página perde a referência do navegador ao envio. Você pode iniciar outro envio. Partes incompletas ficam no diretório privado `uploads/`.
- Um arquivo concluído fica em `files/`, mesmo se você cancelar o formulário antes de salvar. Não há exclusão automática ou botão destrutivo na biblioteca.
- Partes já confirmadas não são gravadas duas vezes. Partes interrompidas são descartadas até o último offset confirmado.
- Se o processo cair durante um envio, pode restar `.lock` no diretório daquela tentativa. Inicie uma nova tentativa. Para limpeza manual de partes/locks antigos, pare o app e remova apenas diretórios de tentativas abandonadas em `uploads/`; nunca remova `files/` para resolver um envio.
- O limite de cada requisição é cerca de 4 MiB. Se o host retornar 413/403, peça ajuste do limite/ModSecurity para as rotas autenticadas `/api/admin/uploads/`. O limite total do arquivo é independente desse limite por parte.
- Faça backup separado de `ARKVIDEO_MEDIA_DIR` e das tabelas Teable. Restaurar somente o banco não restaura os vídeos.

## Rotas e proteção

| Rota | Acesso |
|---|---|
| `/` | Painel com sessão nativa válida |
| `/login` | Login nativo em português |
| `/api/admin/uploads` e subrotas | Sessão válida + origem HTTPS configurada + proprietário do envio |
| `/embed/{UUID}` | Vídeo ativo; campos públicos mínimos; CSP frame-ancestors |
| `/api/playback/start` e `/api/playback/event` | Tickets/tokens validados; nenhuma escrita por record ID fornecido pelo visitante |
| `/media/{UUID}.mp4` | Arquivo público, GET/HEAD/Range, sem listagem de diretórios |

Arquivos locais não são gravados na Teable e nunca são usados como caminho de disco a partir do nome original. A rota de mídia aceita apenas o nome aleatório validado, suporta Range/HEAD para seek e responde como `video/mp4` com `nosniff`. CORS permite reprodução pública do arquivo.

**Domínios autorizados restringem a incorporação do player, não o arquivo.** Não é DRM. Quem tiver uma URL de mídia pública poderá abri-la ou baixá-la. Pausar um vídeo interrompe novas consultas do player/telemetria, mas não remove o arquivo público do cPanel. Links externos assinados continuam vencendo no prazo do provedor.

Prévias administrativas não gravam métricas. O player de produção registra sessões carregadas antes do primeiro play, para calcular taxa de play. Tempo/retensão vêm de eventos coerentes, com heartbeats agrupados. Retenção do player incluído tem resolução de 5 segundos; a visualização agrupa em faixas de 10%. Eventos perdidos ou limites de API podem reduzir os dados; isso não é prova de atenção humana.

## Verificação incluída

```sh
pnpm test
pnpm typecheck
pnpm build
```

Os testes usam adaptadores/arquivos temporários, sem inserir dados nas tabelas reais. Cobrem validações, ações protegidas, tickets, sequências, retenção, CSP, upload em partes, proprietário, retomada, duplicatas, cabeçalho MP4 e byte ranges. O pacote deve ser validado novamente no cPanel para comprovar permissões, quota, Passenger, HTTPS, acesso Teable e conclusão real do login.

## Problemas comuns

- **503 ao iniciar:** confira a versão Node, variáveis, build e o log de erros do Passenger no cPanel. `pnpm check:config` aponta ausências locais.
- **Google retorna à Teable sem concluir no cPanel:** permita pop-ups, confira publicação do app Teable original e suporte ao token/API externos. Não crie credenciais Google paralelas sem decidir uma migração de autenticação.
- **Sem acesso:** use uma conta existente em Acessos ArkVideo. Não altere `existing-only` para liberar o painel publicamente.
- **Upload falha por espaço:** confira a quota real da conta e permissão de escrita. Aumentar a variável de limite não cria espaço em disco.
- **Vídeo sem som/imagem:** verifique codec MP4 no navegador; para fontes externas, confira CORS, token e formato selecionado.
- **Build excede memória:** peça mais recursos temporários ao host ou compile em Linux compatível e envie o resultado normal `.next` + código, sem substituir as dependências da conta por módulos de Windows/macOS.

Referências: [Next.js — custom server](https://nextjs.org/docs/app/guides/custom-server), [Passenger — reverse port binding](https://www.phusionpassenger.com/docs/advanced_guides/in_depth/node/reverse_port_binding.html), [cPanel — Node.js](https://docs.cpanel.net/knowledge-base/web-services/how-to-install-a-node.js-application/).
