WebSocket API
Referência completa da API WebSocket do Urso Eco. Protocolo, eventos, formato de frames e autenticação.
Visão Geral
O Urso Eco utiliza WebSocket para comunicação bidirecional em tempo real. O protocolo suporta envio e recebimento de áudio em tempo real (bidirecional), com eventos de controle em JSON.
Endpoint
WS wss://api.polarai.com.br/v1/urso-eco/streamProtocolo
1. Conexão
Estabeleça uma conexão WebSocket com o endpoint:
const ws = new WebSocket("wss://api.polarai.com.br/v1/urso-eco/stream");2. Autenticação
Após a conexão, envie uma mensagem de autenticação:
{
"type": "auth",
"api_key": "pk-sua-chave-aqui",
"persona": "assistente_geral",
"config": {
"sample_rate": 16000,
"channels": 1,
"encoding": "pcm_s16le",
"voice": "ana",
"language": "pt-BR",
"enable_transcription": true,
"enable_vad": true
}
}Campos de Autenticação
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type | string | Sim | Deve ser "auth" |
api_key | string | Sim | Chave de API (pk-*) |
persona | string | Não | ID da persona (padrão: "assistente_geral") |
config | object | Não | Configuração de áudio |
config.sample_rate | integer | Não | Taxa de amostragem (padrão: 16000) |
config.channels | integer | Não | Canais de áudio (padrão: 1) |
config.encoding | string | Não | Codificação: "pcm_s16le", "opus" (padrão: "pcm_s16le") |
config.voice | string | Não | ID da voz (padrão: "ana") |
config.language | string | Não | Idioma (padrão: "pt-BR") |
config.enable_transcription | boolean | Não | Enviar texto junto com áudio (padrão: true) |
config.enable_vad | boolean | Não | Detecção de atividade vocal (padrão: true) |
3. Enviar Frames de Áudio
Envie frames de áudio como mensagens binárias (ArrayBuffer):
// Frame de áudio: PCM 16-bit signed little-endian, 16kHz, mono
// Tamanho recomendado: 20ms = 640 bytes (320 samples x 2 bytes)
ws.send(pcmAudioBuffer);4. Receber Respostas
O servidor envia dois tipos de mensagens:
- Binárias: frames de áudio (PCM 16-bit, 24kHz)
- Texto: eventos de controle em JSON
ws.onmessage = (event) => {
if (event.data instanceof Blob) {
// Frame de áudio de resposta
handleAudioFrame(event.data);
} else {
// Evento de controle
const event = JSON.parse(event.data);
handleEvent(event);
}
};Eventos
Eventos do Servidor (recebidos)
session_start
Enviado após autenticação bem-sucedida.
{
"type": "session_start",
"session_id": "sess_abc123",
"persona": "assistente_geral",
"voice": "ana",
"config": {
"sample_rate": 24000,
"channels": 1,
"encoding": "pcm_s16le"
}
}audio_frame
Frame de áudio de resposta (enviado como mensagem binária, não JSON). O áudio é PCM 16-bit signed little-endian, 24kHz, mono.
text_delta
Fragmento de transcrição/texto da resposta (quando enable_transcription é true).
{
"type": "text_delta",
"text": "Olá! Como posso",
"is_final": false
}speech_started
O modelo começou a falar.
{
"type": "speech_started",
"timestamp": 1710000000.123
}speech_ended
O modelo parou de falar.
{
"type": "speech_ended",
"timestamp": 1710000003.456,
"duration_ms": 3333
}user_speech_started
Detecção de fala do usuário (VAD).
{
"type": "user_speech_started",
"timestamp": 1710000004.000
}user_speech_ended
Fim da fala do usuário detectado.
{
"type": "user_speech_ended",
"timestamp": 1710000006.500,
"duration_ms": 2500
}error
Erro durante a sessão.
{
"type": "error",
"code": "rate_limited",
"message": "Rate limit excedido. Tente novamente em 30 segundos.",
"retry_after": 30
}session_end
Sessão encerrada pelo servidor.
{
"type": "session_end",
"reason": "timeout",
"duration_ms": 300000,
"usage": {
"audio_minutes": 5.0,
"credits_used": 0.50
}
}Eventos do Cliente (enviados)
interrupt
Interromper a resposta atual do modelo.
{
"type": "interrupt"
}config_update
Atualizar configuração durante a sessão.
{
"type": "config_update",
"config": {
"voice": "pedro",
"enable_transcription": false
}
}end_session
Encerrar a sessão.
{
"type": "end_session"
}Formato de Frame de Áudio
Entrada (cliente para servidor)
| Propriedade | Valor |
|---|---|
| Formato | PCM signed 16-bit little-endian |
| Taxa de amostragem | 16.000 Hz |
| Canais | 1 (mono) |
| Tamanho do frame | 20ms (640 bytes) |
| Byte order | Little-endian |
Saída (servidor para cliente)
| Propriedade | Valor |
|---|---|
| Formato | PCM signed 16-bit little-endian |
| Taxa de amostragem | 24.000 Hz |
| Canais | 1 (mono) |
| Tamanho do frame | 20ms (960 bytes) |
| Byte order | Little-endian |
Códigos de Erro
| Código | Descrição |
|---|---|
auth_failed | Autenticação falhou (API key inválida) |
rate_limited | Rate limit excedido |
invalid_audio | Formato de áudio inválido |
session_timeout | Sessão expirou por inatividade |
server_error | Erro interno do servidor |
persona_not_found | Persona não encontrada |
quota_exceeded | Créditos insuficientes |
Limites
- Duração máxima da sessão: 30 minutos
- Timeout por inatividade: 60 segundos
- Tamanho máximo do frame: 32KB
- Conexões simultâneas por API key: 5