# Legendei

App que coloca legenda em vídeo automaticamente. Roda inteiro no computador da
pessoa: nenhum arquivo sobe pra internet.

## Se a pessoa pedir pra instalar, começar, ou disser que não sabe usar

Rode isto e devolva o link:

```bash
python instalar.py --instalar-ffmpeg && python iniciar.py
```

Avise antes que a primeira vez baixa cerca de 500 MB e demora alguns minutos.

O `--instalar-ffmpeg` só age se o ffmpeg faltar; se já existe, é ignorado. O
instalador pode rodar quantas vezes quiser, não estraga nada. Ele confere o
Python e o ffmpeg, cria o `.venv`, instala as bibliotecas, baixa as 67 fontes e o
modelo de transcrição (~465 MB, só na primeira vez).

Ele encontra o ffmpeg mesmo quando o PATH do terminal ainda está velho, porque
procura nas pastas onde o winget instala. Não peça para a pessoa reabrir o
terminal antes de tentar.

Depois `iniciar.py` sobe o servidor e abre o navegador em `http://localhost:8123`.
Se a porta estiver ocupada ele usa a próxima livre e avisa qual no terminal.

**Nunca rode `app/servidor.py` direto pelo Bash em segundo plano sem avisar**: ele
segura o terminal enquanto estiver no ar, que é o comportamento certo.

## Se der erro

| O que aparece | O que é |
|---|---|
| `ffmpeg nao esta instalado` | rode `python instalar.py --instalar-ffmpeg` |
| `Faltam as fontes das legendas` | rodar `python instalar.py` de novo |
| `Nao achei nenhuma porta livre` | outra cópia do app já está aberta |
| ffmpeg reclamando de `NaN` no áudio | veja "Não tente de novo" abaixo |

## Como o projeto está organizado

```
instalar.py / instalar.bat   prepara tudo
iniciar.py  / iniciar.bat    liga o app e abre o navegador
app/servidor.py              o programa inteiro: API, transcrição, corte, legenda
app/estilos.json             os 88 estilos (GERADO - não editar à mão)
app/fontes.json              as 67 fontes (GERADO - não editar à mão)
app/ferramentas/gerar_estilos.py   a tabela dos estilos; edite AQUI
app/ferramentas/baixar_fontes.py   baixa e prepara as fontes
static/index.html            a tela inteira (HTML, CSS e JS num arquivo só)
static/fonts/                as fontes, usadas na prévia E na queima no vídeo
static/exemplos/             vídeos de teste com voz em português
trabalhos/                   um diretório por vídeo enviado (pode apagar)
models/                      o modelo de transcrição baixado
```

## Regras deste projeto

**Estilos são gerados, não escritos.** Para criar ou mudar um estilo, edite a
tabela `TABELA` em `app/ferramentas/gerar_estilos.py` e rode:

```bash
.venv/Scripts/python.exe app/ferramentas/gerar_estilos.py
```

Editar `app/estilos.json` na mão funciona até alguém rodar o gerador e perder tudo.

**A prévia e o vídeo são desenhados por dois códigos diferentes.** O navegador
desenha em HTML (`capHTML` em `static/index.html`) e o ffmpeg desenha em ASS
(`build_ass` em `app/servidor.py`). Eles compartilham a mesma lógica de layout
(quebra de linha, cor por palavra, encolher pra caber). **Mexer num sem mexer no
outro faz a prévia mentir sobre o resultado.**

**Quem decide o que cortar é o servidor.** A tela chama `/api/plan`, que usa a
mesma função que gera o vídeo. Não reimplemente essa conta no navegador.

**As fontes vêm de arquivos locais.** O ffmpeg escolhe a fonte pelo nome que está
DENTRO do arquivo, não pelo nome do arquivo, e o `baixar_fontes.py` carimba um nome
único em cada um. Se o nome não bater, o vídeo sai com outra fonte, em silêncio.

**Fonte variável sai no peso errado.** O ffmpeg ignora os eixos e desenha a
instância padrão. Por isso `baixar_fontes.py` fatia tudo em versão estática. Ao
adicionar uma fonte nova, confira que ela não aparece como `AINDA VARIAVEL`.

## Não tente de novo (já testamos, não funciona)

**`arnndn` para remover ruído.** É o filtro de rede neural do ffmpeg e parece a
escolha óbvia. Neste build ele solta valores inválidos (`NaN`) no meio do áudio e
derruba o codificador AAC. Testado com os três modelos oficiais do rnnoise: falha
de forma intermitente em cerca de 9 de 10 execuções, e o mesmo comando às vezes
passa, o que engana. O `afftdn` calibrado pelo piso de ruído medido passou em
todas e entrega 25 dB de redução. Está em `audio_chain()`.

**Cortar "né", "tipo", "então" ou "é" sozinho na edição automática.** Muda o
sentido da frase, e em português "é" é o verbo ser. Só formas alongadas ("ééé")
contam como hesitação. Está em `HESITACAO`, em `app/servidor.py`.

**Caminho absoluto do Windows dentro de um filtro do ffmpeg.** O `:` do `D:` é
lido como separador de opção e quebra a linha de filtros. Use caminho relativo: o
ffmpeg roda com o diretório do projeto como pasta atual.

## Para acelerar (opcional, exige placa NVIDIA)

```bash
set LEGENDEI_DEVICE=cuda
set LEGENDEI_ENCODER=h264_nvenc
```

`LEGENDEI_MODEL` aceita `tiny`, `base`, `small` (padrão), `medium` e `large-v3`.
Quanto maior, melhor a transcrição e mais lento.

## Como falar com o dono deste projeto

Português simples, sem jargão. Ele não acompanha termos técnicos: fale em
"o vídeo", "a legenda", "a pasta", não em "endpoint", "pipeline" ou "commit".
