WebSockets na Voice API da Vonage
Este guia explica como os WebSockets se integram à Voice API da Vonage e ajudam você a desenvolver Applications sofisticadas em tempo real, como bots de voz com inteligência artificial ou serviços de transcrição ao vivo.
O que são WebSockets?
Os WebSockets são um protocolo de comunicação que oferece um conexão persistente e full-duplex entre uma aplicação e a plataforma Vonage Voice.
Ao contrário do HTTP, que exige uma solicitação separada para cada troca de dados, um WebSocket mantém uma única conexão aberta, pela qual as mensagens podem ser enviadas em ambas as direções a qualquer momento.
Isso é ideal para situações que exigem dados em streaming de baixa latência, como enviar e receber pacotes de áudio em tempo real.
Por que os WebSockets são importantes para os conectores de IA?
Em applications de voz com IA, muitas vezes é necessário:
- Receber áudio ao vivo de alguém que ligou.
- Transcrever esse áudio ao vivo.
- Enviar respostas em áudio sintetizado de volta para quem ligou.
- Enviar metadados para a sessão.
- Sinais de controle de troca dinamicamente.
Os WebSockets permitem isso da seguinte forma:
- Transmissão de áudio como pacotes binários.
- Troca de mensagens de texto como comandos de controle ou eventos.
- Envio de metadados no início da sessão.
- Permitindo uma interação quase instantânea com serviços de IA, como reconhecimento de fala, NLU ou mecanismos de TTS.
Como configurar um servidor WebSocket em seu aplicativo
Para conectar o Vonage ao seu servidor WebSocket (seu aplicativo), você deve:
- Implantar um ponto de extremidade WebSocket acessível por meio de uma URL segura (wss://).
- Processar conexões recebidas iniciadas pela Vonage.
- Processe ambos mensagens binárias (áudio) e mensagens de texto (Comandos/eventos JSON).
- Opcionalmente, implemente a lógica de autenticação ou autorização.
Exemplo (Node.js, ws):
const WebSocket = require('ws');
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', socket => {
console.log('Vonage connected');
socket.on('message', message => {
if (typeof message === 'string') {
// Handle JSON commands or events
console.log('Text message:', message);
} else {
// Handle binary audio
console.log('Binary audio packet received');
}
});
socket.on('close', () => {
console.log('WebSocket disconnected');
});
});
Utilização de um NCCO para estabelecer a conexão WebSocket
Para instruir a Vonage a transmitir áudio para o seu servidor WebSocket, configure um NCCO (Objeto de Controle de Chamadas da Nexmo) ação do tipo connect:
Exemplo de NCCO:
[
{
"action": "connect",
"endpoint": [
{
"type": "websocket",
"uri": "wss://your-server.example.com",
"content-type": "audio/l16;rate=16000",
"headers": {
"custom-header": "value"
}
}
]
}
]
Formato de áudio:
- Você controla o formato de áudio por meio de
content-type:audio/l16;rate=24000: PCM linear de 16 bits, 24 kHzaudio/l16;rate=16000: PCM linear de 16 bits, 16 kHz (recomendado para reconhecimento de fala).audio/l16;rate=8000: 8 kHz, se necessário.
Autenticação da conexão WebSocket
Quando a Vonage se conectar ao seu servidor WebSocket, talvez você queira verificar se a conexão recebida é da Vonage. Para isso, basta configurar um authorization objeto no endpoint do WebSocket.
Existem dois modos de autorização suportados:
vonage: A Vonage inclui umAuthorizationcabeçalho no handshake inicial do WebSocket, utilizando o mesmo formato de JWT usado para webhooks assinados (Bearer <JWT>). Seu servidor deve validar esse JWT. Consulte Webhooks assinados para obter orientações sobre como validar os JWTs da Vonage.custom: Seu aplicativo oferece umAuthorizationvalor do cabeçalho que a Vonage enviará literalmente no handshake inicial. Isso permite que você utilize seu próprio esquema de autorização e suas próprias credenciais.
Observação: Se authorization se for omitido, defina como null, ou definido como um objeto vazio ({}), a Vonage não aplicará nenhuma medida de autorização para o handshake do WebSocket.
Veja os detalhes no Referência NCCO.
Interação bidirecional: mensagens de áudio e de texto
Da Vonage para o seu aplicativo:
- Mensagens binárias: Trechos de áudio capturados da pessoa que ligou.
- Mensagens de texto: Eventos JSON (por exemplo, conexão aberta, encerrada, notificações).
Trecho da sua aplicação na Vonage:
- Mensagens binárias: Áudio a ser reproduzido para quem está ligando.
- Mensagens de texto: Comandos para controlar a reprodução ou solicitar notificações.
Esse fluxo bidirecional permite:
- Transcrição em tempo real.
- Reprodução de voz sintetizada.
- Controle sobre os buffers de reprodução.
- Interações orientadas por eventos.
Análise de pacotes da Vonage (binário x JSON)
Quando o seu servidor WebSocket recebe uma mensagem:
- Se a mensagem for um Buffer ou um ArrayBuffer:
- É dados de áudio (PCM bruto).
- Se a mensagem for uma string:
- É um Mensagem de controle no formato JSON.
Exemplo de evento JSON:
{
"event":"websocket:connected",
"content-type":"audio/l16;rate=16000",
"prop1": "value1",
"prop2": "value2"
}
Sempre verifique o tipo de mensagem para direcionar a lógica de processamento corretamente.
Tratamento de pacotes de áudio binários recebidos
As mensagens binárias contêm áudio PCM não processado capturado do chamador.
Principais características:
- PCM de 16 bits com sinal, no formato little-endian.
- Taxa de amostragem definida por
content-type(por exemplo, 16.000 Hz). - Cada pacote representa um pequeno trecho de áudio (~20 ms).
Processamento típico:
- Insira o áudio em um mecanismo de reconhecimento de fala.
- Buffer para reprodução posterior.
- Salve no disco para análise.
Envio de pacotes de áudio binários para a Vonage
Para reproduzir um áudio para o chamador:
- Codifique seu áudio como PCM bruto.
- Adapte a taxa de amostragem e o formato especificados no NCCO.
- Envie os dados de áudio como mensagens binárias do WebSocket.
Importante:
O Vonage armazena em buffer o áudio recebido para reproduzi-lo em ordem. Isso permite que você coloque o áudio em fila sem intervalos, mas exige o gerenciamento do buffer, conforme explicado a seguir.
Como funciona o buffer de áudio
Ao enviar pacotes de áudio binários:
- Vonage buffers internamente.
- O tamanho do buffer do WebSocket é de 3.072 pacotes, o que deve ser suficiente para cerca de 60 segundos de áudio.
- A reprodução começa automaticamente.
- Os pacotes subsequentes são colocados na fila.
- Não é possível interromper a reprodução no meio do buffer sem um comando de controle.
Esse design garante uma reprodução contínua, sem interrupções no áudio.
Limpar o buffer de áudio (clear Comando)
Para parar imediatamente reprodução do áudio armazenado no buffer, enviar o clear comando.
Comando de saída (conforme consta em sua inscrição):
{
"action": "clear"
}
` Efeito:
- Todo o áudio na fila é descartado.
- A reprodução é interrompida imediatamente.
Confirmação de recebimento (da plataforma Vonage):
{
"event": "websocket:cleared"
}
Cenário de uso:
É necessário interromper a reprodução para responder dinamicamente à pessoa que está ligando (por exemplo, após a detecção de uma interrupção).
Notificação ao término do áudio (notify Comando)
Para receber uma notificação quando a reprodução do buffer de áudio atual terminar, use o notify comando.
Comando de saída (enviar após um dado de áudio cuja reprodução você deseja saber se já terminou):
{
"action": "notify",
"payload": {
"customKey": "customValue"
}
}
Comportamento:
- Se houver áudio sendo reproduzido, a Vonage envia uma notificação de recebimento ao seu aplicativo assim que a reprodução terminar.
- Se não houver áudio sendo reproduzido, a notificação recebida é reenviada ao seu aplicativo imediatamente.
Notificação de entrada:
{
"event": "websocket:notify",
"payload": {
"customKey": "customValue"
}
}
Cenário de uso:
Sincronize a lógica do seu aplicativo (por exemplo, inicie a gravação ou reproduza um novo prompt assim que o anterior terminar).
Mensagens DTMF em JSON
Se qualquer participante da chamada conectada ao WebSocket enviar um DTMF tom, isso acionará um evento no WebSocket. Esse evento é uma mensagem de texto com uma carga JSON, intercalada entre os quadros de áudio e com o seguinte formato:
{
"event": "websocket:dtmf",
"digit": "5",
"duration": 260
}
Você receberá um evento para cada tecla pressionada, e cada evento conterá apenas um dígito:
eventpermite identificá-lo como um evento DTMF.digitcontém o dígito digitado0-9,*, ou#.durationé o tempo em que a tecla ficou pressionada, em milissegundos; na maioria dos sistemas de telefonia digital, esse valor é fixo.
Como ouvir um participante específico em uma conversa com vários participantes
Quando seu aplicativo participa de um conversa em chamadas com vários participantes — como um cliente e um agente —, talvez seja recomendável que sua conexão WebSocket receber apenas o áudio de um participante específico em vez de todo o áudio mixado.
Isso se chama controle seletivo de áudio, e isso é feito por meio do canHear e canSpeak propriedades do NCCO conversation ação.
Por que você usaria isso?
- Análise de fala: Registre apenas o que o cliente diz, sem levar em conta o que o atendente diz.
- Transcrição em tempo real: Registre os dados do cliente para fins de conformidade.
- Sugestões do Whisper: Envie apenas o áudio para o atendente, sem que o cliente ouça.
Como configurar a escuta seletiva
Para configurar isso:
- Criar uma conversa com nome (por exemplo,
"customer_support"). - Conecte as linhas de chamada do cliente e do agente à conversa.
- Adicione sua conexão WebSocket à mesma conversa, especificando
canHearecanSpeakconforme necessário.
Exemplo: WebSocket em modo de escuta apenas para o cliente
A seguir, apresentamos um exemplo de NCCO em que:
- O cliente é incluído na conversa.
- O agente foi adicionado à conversa.
- O WebSocket se conecta, mas recebe apenas o áudio do cliente.
Perna do cliente NCCO:
[
{
"action": "conversation",
"name": "support_room"
}
]
Agente Leg NCCO:
[
{
"action": "conversation",
"name": "support_room"
}
]
Etapa WebSocket do NCCO:
[
{
"action": "conversation",
"name": "support_room",
"canHear": ["6a4d6af0-55a6-4667-be90-8614e4c8e83c"], // Customer leg ID
"canSpeak": []
}
]
Como isso funciona:
- O WebSocket só ouve o
customerparticipante. - Isso não reenvia nenhum áudio para a conversa (
canSpeak(está vazio). - Se você quiser que o sistema insira áudio (por exemplo, comandos de IA) e reproduza esse áudio apenas para um participante específico, você pode incluir o ID da chamada (leg) desse participante em
canSpeak. - Se você quiser que ele insira áudio (por exemplo, comandos de IA) e reproduza o áudio para todos os participantes, não inclua
canSpeakparâmetro.
Como lidar com desconexões do WebSocket e opções alternativas
Ao usar WebSockets com a Voice API da Vonage, você não depende apenas do próprio WebSocket para saber o que está acontecendo.
A Vonage também envia callbacks de eventos para o seu webhook eventUrl. Essas solicitações HTTP POST fornecem informações confiáveis sobre o status da chamada e permitem um comportamento alternativo caso a conexão WebSocket falhe.
Isso é importante porque simplesmente observar o fechamento do WebSocket não indica por que ela foi encerrada. Você precisa do webhook de evento para determinar se o desligamento foi intencional ou causado por um erro.
Por que isso é importante?
Ao desenvolver experiências de voz para produção — especialmente aquelas baseadas em IA ou em tempo real —, as conexões podem ser interrompidas de forma imprevisível (por exemplo, falhas no servidor, tempo limite de conexão de rede).
Para proporcionar uma experiência agradável ao usuário que está ligando, você pode implementar estratégias alternativas como reproduzir uma mensagem de áudio, transferir a chamada para um atendente humano ou encerrar a ligação educadamente.
Os eventos de webhook oferecem um mecanismo confiável para detectar essas situações e agir de acordo.
Como a Vonage avisa você sobre eventos do WebSocket
Sempre que houver uma mudança significativa no status da conexão WebSocket, a Vonage envia um webhook de evento para o seu eventUrl.
Exemplos de status relevantes:
unanswered: A Vonage não conseguiu estabelecer a conexão WebSocket.failed: A tentativa de conexão falhou.disconnected: A conexão WebSocket foi interrompida após ter sido estabelecida.
Cada evento inclui:
- O
uuid,identificar a chamada. - Carimbos de data e hora.
- Qualquer personalização
headersque você especificou no NCCOconnectação. - O campo de status que descreve o que aconteceu.
Exemplo de carga útil de evento fora de conexão
Este evento é disparado quando o WebSocket é desconectado após o estabelecimento da conexão — seja devido a um erro ou porque seu aplicativo o fechou:
{
"from": "442079460000",
"to": "wss://example.com/socket",
"uuid": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"conversation_uuid": "CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"status": "disconnected",
"timestamp": "2020-03-31T12:00:00.000Z",
"headers": {
"caller-id": "447700900123"
}
}
Como distinguir entre desconexões intencionais e não intencionais
É importante entender que:
- Qualquer desconexão, independentemente de seu aplicativo ter fechado o WebSocket intencionalmente ou de ele ter sido encerrado devido a um erro, levanta uma
disconnectedevento. - Se você quiser encerrar intencionalmente Para utilizar o WebSocket sem acionar um mecanismo de fallback, a Vonage recomenda encerrar o trecho da chamada por meio da Voice API da Vonage em vez de simplesmente encerrar a conexão WebSocket.
- Dessa forma, não
disconnectedO webhook é enviado, e você pode ter certeza de que receberádisconnectedapenas para falhas não intencionais.
- Dessa forma, não
Como lidar com conexões com falha durante a configuração
Às vezes, a conexão WebSocket não pode ser estabelecido, para começar (por exemplo, se o seu servidor estiver fora do ar).
Você pode configurar seu connect ação a ser realizada tratamento síncrono de eventos:
Exemplo de NCCO com evento do tipo “síncrono”:
[
{
"action": "connect",
"eventType": "synchronous",
"eventUrl": [
"https://example.com/events"
],
"from": "447700900000",
"endpoint": [
{
"type": "websocket",
"uri": "wss://example.com/socket",
"content-type": "audio/l16;rate=16000",
"headers": {
"caller-id": "447700900123"
}
}
]
}
]
Como funciona:
- Se a tentativa de conexão falhar, a Vonage envia imediatamente um evento via POST para o seu
eventUrl. - O evento
statusseráunansweredoufailed. - Você pode responder com um novo NCCO descrevendo o comportamento alternativo, como reproduzir uma mensagem ou redirecionar a chamada.
Exemplo de carga útil do evento de falha de conexão
{
"from": "442079460000",
"to": "wss://example.com/socket",
"uuid": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"conversation_uuid": "CON-aaaaaaaa-bbbb-cccc-dddd-0123456789ab",
"status": "unanswered",
"timestamp": "2020-03-31T12:00:00.000Z",
"headers": {
"caller-id": "447700900123"
}
}
Implementação de estratégias alternativas
Quando você receber um webhook com status: disconnected, failed, ou unanswered, você pode:
- Retornar um novo NCCO na resposta do seu webhook para lidar com o plano alternativo (por exemplo, reproduzir um aviso).
- Permitir que o NCCO original continue, caso haja ações adicionais.
- Encerrar a ligação, caso não seja especificada nenhuma outra ação.
Exemplo de NCCO alternativo:
[
{
"action": "talk",
"text": "We are unable to connect you at the moment. Please try again later."
}
]
Conexão com mecanismos de IA
Veja abaixo exemplos de Applications da Vonage para conexão com os principais mecanismos de IA:
- Amazon Nova Sonic: Conversão de Texto em Fala
- Cartesia: Conversão de Texto em Fala
- Deepgram: Conversão de Fala em Texto
- Deepgram: Conversão de fala em texto para o Vonage AI Studio
- Deepgram: Conversão de fala em texto / OpenAI LLM / ElevenLabs: Conversão de texto em fala
- Deepgram: Conversão de voz para voz do agente de voz
- IA Conversacional da ElevenLabs
- API em tempo real da OpenAI