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:

  1. Implantar um ponto de extremidade WebSocket acessível por meio de uma URL segura (wss://).
  2. Processar conexões recebidas iniciadas pela Vonage.
  3. Processe ambos mensagens binárias (áudio) e mensagens de texto (Comandos/eventos JSON).
  4. 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 kHz
    • audio/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 um Authorization cabeç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 um Authorization valor 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:

  1. Codifique seu áudio como PCM bruto.
  2. Adapte a taxa de amostragem e o formato especificados no NCCO.
  3. 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:

  • event permite identificá-lo como um evento DTMF.
  • digit contém o dígito digitado 0-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:

  1. Criar uma conversa com nome (por exemplo, "customer_support").
  2. Conecte as linhas de chamada do cliente e do agente à conversa.
  3. Adicione sua conexão WebSocket à mesma conversa, especificando canHear e canSpeak conforme 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 customer participante.
  • 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 canSpeak parâ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 headers que você especificou no NCCO connect açã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 disconnected evento.
  • 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 disconnected O webhook é enviado, e você pode ter certeza de que receberá disconnected apenas para falhas não intencionais.

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 status será unanswered ou failed.
  • 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: