# VEX-TTS

VEX-TTS, tecnologia Auxyra, transforma texto em áudio por HTTP.

Endpoint público:

```text
GET https://tts.auxyra.com.br/v1
Header: X-VEX-Token: <token>
```

A página `https://tts.auxyra.com.br/v1/test` permite informar a chave, escolher voz e formato, escrever o texto e ouvir o áudio. Os endpoints públicos de integração são somente a síntese e a consulta autenticada de limites. Não existem endpoints de status ou documentação automática.

## Parâmetros

- `text`: texto que será sintetizado. Envie com URL encoding.
- `model`: voz disponibilizada pelo servidor, por exemplo, `julia` ou `luisa`.
- `format`: `wav`, `mp3`, `ogg`, `opus` ou `webm`.

O servidor devolve os bytes do áudio diretamente. WAV usa PCM16 mono/8 kHz. MP3, OGG, Opus e WebM recebem o PCM na taxa nativa da voz; a taxa efetiva final segue o codec solicitado.

## Tags sequenciais

As tags abaixo podem aparecer no próprio `text` e alteram os trechos seguintes:

- `<break=500>`: insere silêncio em milissegundos. Limites: 10.000 ms por tag e 30.000 ms na requisição.
- `<model=jeff>`: troca a voz. `<model=default>` retorna ao modelo da query.
- `<speed=1.5>`: define a velocidade de `0.5` a `2.0`. `<speed=1>` restaura a velocidade normal.
- `<volume=0.5>`: define o volume de `0.0` a `2.0`. `<volume=1>` restaura o volume normal.
- `<playback=bomdia.wav>`: insere uma gravação da biblioteca no ponto da tag, usando a velocidade e o volume ativos.

O estado persiste até que outra tag altere o mesmo controle. Nomes de tags ignoram caixa e aceitam espaços ao redor de `=`. Todas as vozes usadas precisam estar permitidas no token e carregadas no servidor. Para sintetizar uma tag literalmente, use uma barra: `\<speed=1.5>`.

Exemplo:

```text
Olá.<break=500> <model=jeff> Agora outra voz.
<speed=1.5> Trecho rápido <speed=0.8> e lento.
<volume=0.5> Fala baixo <volume=1.5> ou mais alto.
```

Tags conhecidas inválidas retornam `422`. Construções desconhecidas, como `<emotion=happy>`, permanecem no texto falado. O limite de caracteres da licença conta o texto bruto depois de `strip`, incluindo as tags.

## Gravações no texto

Disponibilize o arquivo na pasta `medias` dos dados do serviço ou envie pela aba **Mídias** do Admin. Crie pastas e subpastas para organizar por cliente, projeto, locutor ou estilo, abra a pasta desejada e envie vários arquivos para ela. Nomes existentes na mesma pasta não são sobrescritos; pastas diferentes podem conter arquivos com o mesmo nome.

O botão **Ouvir** abre um player flutuante com controles para ouvir novamente e repetir. Ele continua acessível e reproduzindo enquanto você navega pelas pastas. Use os controles de download do próprio player; a tabela mantém somente as ações Ouvir e Excluir.

Nomes e tags longos quebram linha para manter as ações visíveis. Em telas menores, cada arquivo aparece como um cartão com os botões Ouvir e Excluir.

```text
<playback=bomdia.wav> Victor.
<playback=projeto/saudacao.wav> Victor.
<playback=cliente/locutor/estilo/saudacao.wav> Victor.
Olá.<break=200><playback=aviso.mp3> Até logo.
<playback=abertura.flac><playback=encerramento.m4a>
<speed=1.5><volume=0.5><playback=bomdia.wav><speed=1><volume=1> Victor.
```

Cada gravação toca inteira antes do próximo trecho. Os silêncios originais são preservados; use `break` para inserir uma pausa adicional. O formato de entrada pode diferir da saída: gravações com formatos, canais, taxas e profundidades de bits suportados pelo serviço são convertidas automaticamente para o formato solicitado.

Na montagem, o volume percebido de cada gravação é ajustado automaticamente para acompanhar o primeiro trecho de voz audível sintetizada, elevando arquivos baixos e reduzindo os altos. A tag `volume` é aplicada depois desse ajuste e continua permitindo diferenças intencionais. Há proteção contra picos; duração e arquivos originais são preservados. Sem voz audível como referência, as gravações usam um nível comum de -20 LUFS. A prévia no Admin toca a gravação original convertida, sem esse ajuste da montagem.

Use o caminho relativo à biblioteca, separando pastas com `/` e preservando nomes, extensão e caixa, incluindo espaços e acentos. Arquivos da raiz continuam usando somente o nome. Caminhos absolutos, `..`, links simbólicos e URLs não são aceitos. Qualquer licença válida pode usar a biblioteca, mas a listagem e o gerenciamento ficam no Admin.

Chamadas contendo somente gravações também exigem token, `model` e `format`, com as mesmas validações da licença e do modelo. Os formatos comprimidos usam a taxa da primeira voz sintetizada, ou 16 kHz quando não há fala; WAV continua mono/8 kHz. `X-VEX-Models` fica vazio e `X-VEX-Elapsed-Ms` vale zero quando não há síntese de voz.

Uma referência inválida ou ausente retorna `422` antes de consumir cota. Uma gravação indecodificável descoberta durante o processamento também retorna `422`, libera a concorrência e mantém a cobrança da chamada já iniciada.

## Normalização de números

Por padrão, o VEX-TTS tenta converter automaticamente números em formato pt-BR antes da síntese:

```text
Ficou em 20 lugar.       -> Ficou em vinte lugar.
Desconto de 20%.         -> Desconto de vinte por cento.
Valor R$ 20,50.          -> Valor vinte reais e cinquenta centavos.
Data 20/05/2026.         -> Data vinte de maio de dois mil e vinte e seis.
Horário 14:30.           -> Horário catorze horas e trinta minutos.
Ficou em 20º lugar.      -> Ficou em vigésimo lugar.
```

Quando o significado automático não for o desejado, use uma região `read`. Ela afeta somente o conteúdo imediatamente entre `{` e `}` e não precisa de fechamento ou redefinição:

- `<read=cardinal>{2026}`: número cardinal.
- `<read=ordinal>{20}`: ordinal masculino.
- `<read=digits>{080012}`: dígitos separados.
- `<read=raw>{2.10.5}`: desativa a expansão numérica automática nessa região e preserva o conteúdo para o processamento VEX-TTS.

Exemplos:

```text
O número <read=cardinal>{2026}.
Ficou em <read=ordinal>{20} lugar.
Código <read=digits>{2026}.
```

Não existem `<read=auto>` nem `<read=default>`: a leitura automática volta imediatamente depois da chave `}`. Números são limitados a 18 dígitos para conversão cardinal/ordinal. Uma região `read` inválida retorna `422` antes de consumir a cota.

## Exemplo

```http
GET /v1?text=Ol%C3%A1.%3Cbreak%3D500%3E%20%3Cmodel%3Djeff%3E%20Outra%20voz.&model=faber&format=mp3 HTTP/1.1
Host: tts.auxyra.com.br
X-VEX-Token: SEU_TOKEN
```

## Cabeçalhos da resposta

- `Content-Type`: MIME correspondente ao formato solicitado.
- `Content-Disposition`: nome sugerido para o arquivo, no modo `inline`.
- `X-Request-ID`: identificador da requisição.
- `X-VEX-Model`: modelo padrão recebido na query.
- `X-VEX-Models`: vozes efetivamente sintetizadas, na ordem da primeira utilização.
- `X-VEX-Elapsed-Ms`: tempo de processamento de voz medido pelo VEX-TTS.
- `Cache-Control: no-store`: impede o cache do áudio autenticado.

## Modelos e limites restantes

Consulte a licença sem consumir requisições ou caracteres:

```http
GET /v1/limits HTTP/1.1
Host: tts.auxyra.com.br
X-VEX-Token: SEU_TOKEN
```

Resposta:

```json
{
  "models": [
    {"name": "julia", "available": true},
    {"name": "luisa", "available": false}
  ],
  "requests": {"max": 1000, "used": 120, "remaining": 880},
  "characters_per_request": {"max": 500},
  "characters_daily": {"max": 500000, "used": 42000, "remaining": 458000},
  "concurrent": {"max": 2, "used": 1, "remaining": 1},
  "expires_at": "2026-08-01",
  "reset_timezone": "America/Sao_Paulo",
  "last_reset_date": "2026-07-02"
}
```

- `available=false` significa que a voz é permitida pela licença, mas não está disponível no serviço naquele momento.
- `expires_at` é a data de validade da licença, inclusiva no fuso de renovação dos limites.
- Limites ilimitados usam `-1` em `max` e `remaining`.
- `used` em `concurrent` representa requisições ativas no momento da consulta.

## Erros

- `401`: token ausente ou inválido.
- `403`: licença inativa, expirada ou sem permissão para o modelo.
- `409`: limite concorrente atingido; tente novamente com backoff curto.
- `429`: limite diário de requisições ou caracteres atingido.
- `422`: texto, tag, modelo ou formato inválido, ou texto acima do limite da licença.
- `503`: voz indisponível ou falha temporária do serviço de síntese.

O texto faz parte da URL por exigência deste contrato GET. Clientes e proxies devem evitar registrar query strings.
