Pular para o conteúdo
int8labs

Avatar

O Gustavo ou a Helena fala um texto (voz e boca) ou dubla um áudio seu (só a boca). Uma conexão, várias falas, uma de cada vez. Escopo avatar; R$ 0,20 por minuto de fala, voz incluída.

1 min de leitura · atualizado em 13/10/2026
WSwss://api.int8labs.com/v1/avatar/stream

Autenticação

No servidor, Authorization: Bearer int8_live_… no handshake. No navegador, ?token=int8_tmp_… na URL (um token de POST /v1/tokens). O SDK web faz tudo isto por você.

Parâmetros

  • avatar (opcional): gustavo (o padrão) ou helena. Escolhe quem fala: o rosto que o seu renderizador desenha, a voz e a boca. Outro valor recebe invalid_request e o fechamento 4400, antes de qualquer cobrança.
  • token: só no navegador, o token temporário (veja acima).

Mensagens

VOCÊ →"speak"

Modo texto: até 1.000 caracteres, com a voz do avatar da conexão.

{"type":"speak","text":"Olá! Como posso ajudar?"}
VOCÊ →"audio.start"

Modo áudio próprio: a taxa do seu áudio (8000, 16000, 22050, 24000, 44100 ou 48000).

{"type":"audio.start","sample_rate":16000}
VOCÊ →áudiobinário

No modo áudio próprio: o som que a boca vai dublar, até 5 minutos por fala.

PCM16 LE mono, até 1 s por mensagem
VOCÊ →"audio.end"

Fim do áudio da fala.

{"type":"audio.end"}
← SERVIDOR"start"

A fala começou. mode é text ou audio; no modo texto o áudio sai a 44100 Hz.

{"type":"start","utterance_id":"utt_01JAA5B3N9P2Q4R6S8T0V1W3XY","sample_rate":44100,"mode":"text"}
← SERVIDOR0x01 áudiobinário

Só no modo texto: a voz do avatar, em pedaços.

0x01 · índice do pedaço (uint16 LE) · PCM16 LE mono
← SERVIDOR0x02 rostobinário

A boca e a expressão, para o renderizador do avatar. O SDK web lê esses pacotes por você.

0x02 · pacote de rosto (25 quadros por segundo, 103 valores fp16 por quadro)
← SERVIDOR"done"

Fim da fala: duração, custo e saldo.

{"type":"done","utterance_id":"utt_01JAA5B3N9P2Q4R6S8T0V1W3XY","audio_ms":2140,"cost_brl":0.00713333,"balance_brl":87.39286667}
← SERVIDOR"error"

Erro, com o mesmo code do REST. Os que fecham a conexão vêm seguidos do fechamento 4000 + o status HTTP.

{"type":"error","code":"insufficient_balance","message":"Saldo insuficiente. Recarregue em console › Faturamento.","request_id":"req_01JAA4M7Q2W8E5R3T6Y9U1I0PZ"}

Regras

  • O parâmetro avatar da URL escolhe quem fala: gustavo (o padrão) ou helena. Cada um tem a sua voz e a sua boca. Outro valor recebe invalid_request e o fechamento 4400, antes de qualquer cobrança.
  • No modo texto, erros de uma fala (invalid_request, payload_too_large, server_busy, concurrency_limited) chegam sem fechar a conexão. No modo áudio próprio, todo erro fecha.
  • Áudio próprio parado por 10 s sem audio.end fecha com 4400. Fala acima de 5 minutos fecha com 4413.
  • Sem mensagem por 5 minutos, ou depois de 4 horas de sessão, a conexão fecha com 1000.
  • A credencial é conferida antes de cada fala: chave revogada ou token vencido fecha com 4401.
  • O SDK web (createAvatar) cuida de tudo isto e da sincronia da boca com o som.

Fechamentos

FechamentoQuando
1000Fim normal: depois do done da transcrição ao vivo, por ociosidade ou ao passar de 4 h de sessão.
4400invalid_request na transcrição ao vivo ou no modo áudio do avatar. Na voz e no modo texto do avatar, o erro de uma fala chega sem fechar a conexão.
4401invalid_api_key, api_key_expired ou api_key_revoked, no começo ou no meio da sessão. Na transcrição ao vivo, os final do áudio já recebido chegam antes do erro.
4402insufficient_balance: o saldo acabou. O que já foi falado ou ouvido é cobrado; na transcrição ao vivo, os final desse áudio chegam antes do erro.
4403ip_not_allowed ou scope_denied.
4413payload_too_large no modo áudio do avatar (fala acima de 5 min).
4429rate_limited (áudio mais rápido que o tempo real) ou concurrency_limited (WebSockets demais na organização).
4500internal_error.
4503server_busy ou model_unavailable.

Exemplo

import asyncio
import json
import os
​
import websockets # pip install "websockets>=14"
​
​
async def main() -> None:
# avatar=gustavo (o padrão) ou helena: o rosto, a voz e a boca.
async with websockets.connect(
"wss://api.int8labs.com/v1/avatar/stream?avatar=helena",
additional_headers={"Authorization": f"Bearer {os.environ['INT8_API_KEY']}"},
) as ws:
await ws.send(json.dumps({"type": "speak", "text": "Olá! Como posso ajudar?"}))
audio, pacotes = bytearray(), 0
async for mensagem in ws:
if isinstance(mensagem, bytes):
if mensagem[0] == 0x01:
audio += mensagem[3:] # PCM16 LE mono, 44100 Hz
elif mensagem[0] == 0x02:
pacotes += 1 # pacote de rosto, para o renderizador
continue
evento = json.loads(mensagem)
if evento["type"] == "done":
print(evento["audio_ms"], "ms;", pacotes, "pacotes de rosto; R$", evento["cost_brl"])
break
​
​
asyncio.run(main())