WebSockets en la Voice API de Vonage

Esta guía explica cómo se integran los WebSockets con la Voice API de Vonage y cómo te ayudan a crear aplicaciones sofisticadas en tiempo real, como bots de voz basados en inteligencia artificial o servicios de transcripción en directo.

¿Qué son los WebSockets?

Los WebSockets son un protocolo de comunicación que proporciona un conexión persistente y de dúplex completo entre una aplicación y la plataforma Vonage Voice.
A diferencia de HTTP, que requiere una solicitud independiente para cada intercambio, un WebSocket mantiene una única conexión abierta a través de la cual se pueden enviar mensajes en ambas direcciones en cualquier momento.

Esto resulta ideal para situaciones en las que se requiere flujo de datos de baja latencia, como el envío y la recepción de paquetes de audio en tiempo real.

¿Por qué son importantes los WebSockets para los conectores de IA?

En las aplicaciones de voz de IA, a menudo es necesario:

  • Recibir audio en directo de una persona que ha llamado.
  • Transcriba ese audio en directo.
  • Enviar respuestas de audio sintetizadas a la persona que llama.
  • Enviar metadatos para la sesión.
  • Intercambiar señales de control de forma dinámica.

Los WebSockets lo hacen posible de la siguiente manera:

  • Transmisión de audio en forma de paquetes binarios.
  • Intercambio de mensajes de texto como órdenes de control o eventos.
  • Envío de metadatos al inicio de la sesión.
  • Permitir una interacción casi instantánea con los servicios de IA, como los motores de reconocimiento de voz, NLU o TTS.

Configuración de un servidor WebSocket en su aplicación

Para conectar Vonage a tu servidor WebSocket (tu aplicación), debes:

  1. Despliegue de un punto final WebSocket accesible a través de una URL segura (wss://).
  2. Maneja las conexiones entrantes iniciadas por Vonage.
  3. Procesar ambos mensajes binarios (audio) y mensajes de texto (comandos/eventos JSON).
  4. Opcionalmente, implementar la lógica de autenticación o autorización.

Ejemplo (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');
  });
});

Uso de una OCN para establecer la conexión WebSocket

Para indicar a Vonage que transmita el audio a tu servidor WebSocket, configura un NCCO (Objeto de control de llamadas de Nexmo) acción de tipo connect:

Ejemplo OCN:

[
  {
    "action": "connect",
    "endpoint": [
      {
        "type": "websocket",
        "uri": "wss://your-server.example.com",
        "content-type": "audio/l16;rate=16000",
        "headers": {
          "custom-header": "value"
        }
      }
    ]
  }
]

Formato de audio:

  • El formato de audio se controla mediante content-type:
    • audio/l16;rate=24000: PCM lineal de 16 bits, 24 kHz
    • audio/l16;rate=16000: PCM lineal de 16 bits, 16 kHz (recomendado para el reconocimiento de voz).
    • audio/l16;rate=80008kHz si es necesario.

Autenticación de la conexión WebSocket

Cuando Vonage se conecta a tu servidor WebSocket, es posible que desees verificar que la conexión entrante provenga de Vonage. Puedes hacerlo configurando un authorization en el extremo WebSocket.

Hay dos modos de autorización compatibles:

  • vonage: Vonage incluye un Authorization encabezado en el protocolo de enlace inicial de WebSocket utilizando el mismo formato JWT que se emplea para los webhooks firmados (Bearer <JWT>). Tu servidor debería validar este JWT. Consulta Webhooks firmados para obtener instrucciones sobre cómo validar los JWT de Vonage.
  • custom: Tu solicitud incluye un Authorization valor de encabezado que Vonage enviará tal cual en el protocolo de establecimiento de conexión inicial. Esto te permite utilizar tu propio sistema de autorización y tus propias credenciales.

Nota: Si authorization si se omite, se establece en null, o bien se establece en un objeto vacío ({}), Vonage no aplicará ningún procedimiento de autorización para el protocolo de establecimiento de conexión de WebSocket.

Consulte los detalles en el Referencia OCNC.

Interacción bidireccional: mensajes de audio y de texto

De Vonage a su aplicación:

  • Mensajes binarios: Trozos de audio capturados de la persona que llama.
  • Mensajes de texto: Eventos JSON (por ejemplo, conexión abierta, conexión cerrada, notificaciones).

De tu aplicación a Vonage:

  • Mensajes binarios: Audio que se reproducirá para la persona que llama.
  • Mensajes de texto: Comandos para controlar la reproducción o solicitar notificaciones.

Este flujo bidireccional permite:

  • Transcripción en tiempo real.
  • Reproducción de voz sintetizada.
  • Control de los búferes de reproducción.
  • Interacciones basadas en eventos.

Análisis de los paquetes de Vonage (binario frente a JSON)

Cuando tu servidor WebSocket reciba un mensaje:

  • Si el mensaje es un Buffer o un ArrayBuffer:
    • Es datos de audio (PCM en bruto).
  • Si el mensaje es una cadena:
    • Es un Mensaje de control en formato JSON.

Ejemplo de evento JSON:

{
    "event":"websocket:connected",
    "content-type":"audio/l16;rate=16000",
    "prop1": "value1",
    "prop2": "value2"
}

Comprueba siempre el tipo de mensaje para dirigir correctamente la lógica de procesamiento.

Gestión de paquetes de audio binarios entrantes

Los mensajes binarios contienen audio PCM sin procesar capturado de la persona que llama.

Características principales:

  • 16-bit signed little-endian PCM.
  • Frecuencia de muestreo definida por content-type (por ejemplo, 16.000 Hz).
  • Cada paquete representa un breve fragmento de audio (aprox. 20 ms).

Procesamiento típico:

  • Introduce el audio en un motor de reconocimiento de voz.
  • Memoria intermedia para la reproducción posterior.
  • Guardar en el disco para su análisis.

Envío de paquetes de audio binarios a Vonage

Para reproducir audio a la persona que llama:

  1. Codifica tu audio como PCM sin procesar.
  2. Adapta la frecuencia de muestreo y el formato especificados en el NCCO.
  3. Envía los datos de audio como mensajes WebSocket binarios.

Importante:
Vonage almacena el audio entrante para reproducirlo en orden. Esto te permite poner audio en cola sin espacios, pero requiere la administración de búfer, que se explica a continuación.

Cómo funciona el búfer de audio

Cuando envías paquetes de audio binarios:

  • Vonage topes a nivel interno.
  • El tamaño del búfer de WebSocket es de 3072 paquetes, lo que debería ser suficiente para unos 60 segundos de audio.
  • La reproducción comienza automáticamente.
  • Los paquetes siguientes se ponen en cola.
  • No se puede interrumpir la reproducción a mitad de búfer sin un comando de control.

Este diseño garantiza una reproducción fluida y sin interrupciones en el audio.

Borrar el búfer de audio (clear Mando)

A detener inmediatamente reproducción del audio almacenado en el búfer, envía el clear mando.

Comando de salida (de su solicitud):

{
  "action": "clear"
}

` Efecto:

  • Se descarta todo el audio en cola.
  • La reproducción se detiene inmediatamente.

Acuse de recibo (de la plataforma Vonage):

{
  "event": "websocket:cleared"
}

Escenario de uso:
Debes interrumpir la reproducción para responder de forma dinámica a la persona que llama (por ejemplo, tras detectar una interrupción).

Notificación de fin de audio (notify Mando)

Para recibir una notificación cuando haya terminado de reproducirse el búfer de audio actual, utiliza la función notify mando.

Comando de salida (enviar después de una carga útil de audio que desea saber si ha terminado de reproducirse):

{
  "action": "notify",
  "payload": {
    "customKey": "customValue"
  }
}

Comportamiento:

  • Si se está reproduciendo audio, Vonage envía una notificación de recepción a tu aplicación una vez finalizada la reproducción.
  • Si no se está reproduciendo audio, la notificación entrante se devuelve a su aplicación. de inmediato.

Notificación de entrada:

{
  "event": "websocket:notify",
  "payload": {
    "customKey": "customValue"
  }
}

Escenario de uso:
Sincronice la lógica de su aplicación (por ejemplo, inicie la grabación o reproduzca un nuevo aviso cuando termine el anterior).

Mensajes DTMF en formato JSON

Si alguno de los participantes en la llamada conectado al WebSocket envía un DTMF se activará un evento en el WebSocket. Este evento es un mensaje de texto con una carga útil JSON, intercalado entre los fotogramas de audio y con el siguiente formato:

{
  "event": "websocket:dtmf",
  "digit": "5",
  "duration": 260
}

Recibirás un evento por cada pulsación de tecla y cada evento contendrá solo un dígito:

  • event te permite identificarlo como un evento DTMF.
  • digit contiene el dígito pulsado 0-9, *, o #.
  • duration es la duración de la pulsación de la tecla en milisegundos; en la mayoría de los sistemas telefónicos digitales será una duración fija.

Escuchar a un participante concreto en una conversación entre varios interlocutores

Cuando tu aplicación participa en un conversación en el caso de llamadas con varios participantes —como un cliente y un agente—, es posible que desees que tu conexión WebSocket recibir solo el audio de un participante concreto en lugar de todo el audio mezclado.

A esto se le llama control de audio selectivoy se consigue utilizando el canHear y canSpeak propiedades del NCCO conversation acción.


¿Para qué se utilizaría esto?

  • Análisis del habla: Capta sólo lo que dice el cliente, ignorando al agente.
  • Transcripción en tiempo real: Registra los datos del cliente a efectos de cumplimiento normativo.
  • Susurros: Enviar audio sólo al agente sin que lo oiga el cliente.

Cómo configurar la escucha selectiva

Para configurarlo:

  1. Crear una conversación con nombre (p. ej., "customer_support").
  2. Conecte los tramos de llamada del cliente y del agente a la conversación.
  3. Añade tu conexión WebSocket a la misma conversaciónespecificando canHear y canSpeak según sea necesario.

Ejemplo: WebSocket escuchando sólo al cliente

A continuación se muestra un ejemplo de NCCO en el que:

  • El cliente se une a la conversación.
  • El agente se une a la conversación.
  • El WebSocket se conecta, pero solo recibe el audio del cliente.

Cliente Leg NCCO:

[
  {
    "action": "conversation",
    "name": "support_room"
  }
]

Agente Leg NCCO:

[
  {
    "action": "conversation",
    "name": "support_room"
  }
]

Sección de WebSocket de la NCCO:

[
  {
    "action": "conversation",
    "name": "support_room",
    "canHear": ["6a4d6af0-55a6-4667-be90-8614e4c8e83c"], // Customer leg ID
    "canSpeak": []
  }
]

Cómo funciona:

  • El WebSocket solo oye el customer participante.
  • En no devuelve ningún sonido a la conversación (canSpeak está vacío).
  • Si desea inyectar audio (por ejemplo, indicaciones de AI) y reproducir el audio sólo a un participante designado, puede incluir el ID de llamada (tramo) del participante en canSpeak.
  • Si desea que inyecte audio (por ejemplo, indicaciones de AI) y reproduzca el audio a todos los participantes, no incluya canSpeak parámetro.

Manejo de desconexiones WebSocket y opciones de Fallback

Cuando utilizas WebSockets con la Voice API de Vonage, no te basas únicamente en el propio WebSocket para saber qué está pasando.
Vonage también envía funciones de llamada de retorno de eventos a tu webhook de eventUrl. Estas peticiones HTTP POST proporcionan información fidedigna sobre el estado de la llamada y permiten un comportamiento alternativo si falla la conexión WebSocket.

Esto es importante porque simplemente observando el cierre de WebSocket no te dice por qué se cerró. Necesita el webhook de eventos para determinar si la desconexión fue intencionada o causada por un error.

¿Por qué es importante esto?

Cuando se crean experiencias de voz de producción, especialmente las impulsadas por IA o en tiempo real, las conexiones pueden fallar de forma impredecible (por ejemplo, caídas del servidor, tiempos de espera de la red).
Para ofrecer una experiencia fluida al usuario que llama, puedes implementar estrategias alternativas como reproducir un aviso, transferir a un agente humano o finalizar la llamada amablemente.

Los eventos Webhook le ofrecen un mecanismo fiable para detectar estas situaciones y actuar en consecuencia.

Cómo Vonage te notifica los eventos WebSocket

Cada vez que se produce un cambio significativo en el estado de la conexión WebSocket, Vonage envía un evento webhook a su eventUrl.

Ejemplos de estados relevantes:

  • unanswered: Vonage no pudo establecer la conexión WebSocket.
  • failed: El intento de conexión ha fallado.
  • disconnected: La conexión WebSocket se ha interrumpido después de establecerse.

Cada acto incluye:

  • El uuid, identificando la llamada.
  • Marcas de tiempo.
  • Cualquier personalización headers que especificó en la OCNC connect acción.
  • Campo de estado que describe lo sucedido.

Ejemplo de carga útil de evento desconectado

Este evento se envía cuando el WebSocket se desconecta después de la conexión - ya sea debido a un error o porque su aplicación lo cerró:

{
  "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"
  }
}

Cómo distinguir las desconexiones intencionadas de las involuntarias

Es importante entenderlo:

  • Cualquier desconexión, tanto si tu aplicación cerró el WebSocket de forma intencionada como si se interrumpió debido a un error, plantea una disconnected evento.
  • Si desea terminar intencionadamente el WebSocket sin activar un fallback, Vonage recomienda terminación del tramo de llamada a través de Voice API de Vonage en lugar de simplemente cerrar la conexión WebSocket.
    • De esta manera, no disconnected Se envía un webhook y puedes estar seguro de que recibirás disconnected solo en caso de fallos involuntarios.

Gestión de conexiones fallidas durante la instalación

A veces, la conexión WebSocket no se puede establecer en primer lugar (por ejemplo, si su servidor está fuera de línea).
Puede configurar su connect acción a realizar gestión síncrona de eventos:

Ejemplo de NCCO con un «eventType» sincrónico:

[
  {
    "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"
        }
      }
    ]
  }
]

Cómo funciona:

  • Si el intento de conexión falla, Vonage envía inmediatamente un evento POST a tu eventUrl.
  • El evento status será unanswered o failed.
  • Puedes responder con una nueva OCN que describe un comportamiento alternativo, como la reproducción de un mensaje o el desvío de la llamada.

Ejemplo de carga útil de un evento de conexión fallida

{
  "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"
  }
}

Aplicación de estrategias de emergencia

Cuando reciba un webhook con status: disconnected, failed, o unansweredpuedes:

  • Devolver un nuevo NCCO en la respuesta de tu webhook para gestionar el caso de fallo (por ejemplo, reproducir un mensaje de aviso).
  • Permitir que la NCCO original siga funcionando, si hay acciones adicionales.
  • Colgar el teléfonosi no se especifica ninguna otra acción.

Ejemplo de OCN de reserva:

[
  {
    "action": "talk",
    "text": "We are unable to connect you at the moment. Please try again later."
  }
]

Conexión con motores de IA

A continuación encontrarás ejemplos de aplicaciones de Vonage para conectarse a los motores de IA más populares: