Noesis / Integrations

Connect a Vonage call to a WebSocket relay and forward its 16-bit PCM audio to Noesis.

The Vonage Voice API connects a call to a WebSocket and sends its audio as binary frames of 16-bit PCM. Run a relay that forwards those frames to Noesis.

1. Connect the call to your relay

In your NCCO, connect the call to the relay's WebSocket. Values in headers arrive in the first message, so use them to pass your call ID:

JSON
[
  {
    "action": "connect",
    "endpoint": [
      {
        "type": "websocket",
        "uri": "wss://relay.example.com/vonage",
        "content-type": "audio/l16;rate=16000",
        "headers": { "call_id": "your-call-id" }
      }
    ]
  }
]

The WebSocket becomes part of the call: Vonage sends it the call's audio and plays back anything it sends. The relay sends nothing back. To keep the call connected to a person or bot at the same time, add the WebSocket as another leg of the same conversation.

2. Forward the audio to Noesis

The relay uses noesis_relay.py from the relay helper:

Python
# vonage_relay.py: Vonage WebSocket -> your server -> Noesis
import asyncio, json

import websockets

from noesis_relay import NoesisCall

async def on_answer(event):
    if event["type"] == "classification":
        print(event["call_id"], event["label"])     # your own logic

async def handle(vonage):
    call = None
    try:
        async for message in vonage:
            if call is None:                        # the first message is JSON with your headers
                info = json.loads(message) if isinstance(message, str) else {}
                call = NoesisCall(on_answer, encoding="pcm_s16le", sample_rate=16000,
                                  call_id=info.get("call_id"))
                await call.open()
            if isinstance(message, bytes):
                await call.send(message)            # 16-bit PCM, 20 ms per frame
    except websockets.ConnectionClosed:
        pass
    if call is not None:
        await call.close()

async def main():
    async with websockets.serve(handle, "0.0.0.0", 8080):
        await asyncio.Future()                      # run until stopped

asyncio.run(main())

For audio/l16;rate=8000, use sample_rate=8000. To not record calls, create each call with record="false" as well.