Noesis / Integrations
Asterisk
Send an Asterisk channel's audio to a relay with AudioSocket, and forward it to Noesis.
Asterisk's AudioSocket (Asterisk 18 and later) sends a channel's audio to a TCP server as 16-bit PCM at 8 kHz. Run a relay that accepts the AudioSocket connection and forwards the audio to Noesis.
1. Send the channel's audio to your relay
In the dialplan, give AudioSocket a UUID for the call and your relay's address:
exten => 100,1,Answer()
same => n,AudioSocket(40325ec2-5efd-4bd3-805f-53576e581d13,relay.example.com:9092)AudioSocket connects the channel to the relay until the connection closes. To listen to a call that continues with a person or bot at the same time, run AudioSocket on a spy channel of the person you called, for example with ChanSpy or an ARI snoop channel.
2. Forward the audio to Noesis
The relay uses noesis_relay.py from the relay helper. Each AudioSocket message is a 1-byte type, a 2-byte length (big-endian) and the payload:
# asterisk_relay.py: Asterisk AudioSocket -> your server -> Noesis
import asyncio, uuid
from noesis_relay import NoesisCall
HANGUP, CALL_UUID, AUDIO = 0x00, 0x01, 0x10
async def on_answer(event):
if event["type"] == "classification":
print(event["call_id"], event["label"]) # your own logic
async def handle(reader, writer):
call = None
try:
while True:
header = await reader.readexactly(3)
kind, size = header[0], int.from_bytes(header[1:3], "big")
payload = await reader.readexactly(size) if size else b""
if kind == CALL_UUID:
call = NoesisCall(on_answer, encoding="pcm_s16le", sample_rate=8000,
call_id=str(uuid.UUID(bytes=payload)))
await call.open()
elif kind == AUDIO and call is not None:
await call.send(payload) # 16-bit PCM, 8 kHz, mono
elif kind == HANGUP:
break
except asyncio.IncompleteReadError:
pass # Asterisk closed the connection
if call is not None:
await call.close()
writer.close()
async def main():
server = await asyncio.start_server(handle, "0.0.0.0", 9092)
async with server:
await server.serve_forever()
asyncio.run(main())To not record calls, create each call with record="false" as well.