Transcript of customer's leg after queuing - Stasis

I was successful in transcribing with the vosk model, using the basic context as below:

[from-internal]

exten => 4,1,Answer()
same => n,Stasis(v)
same => n,Hangup()

Vosk code:

#!/usr/bin/python3

import anyio
import asyncari
import logging
import aioudp
import os
import vosk
import array
import json
ast_host = os.getenv("AST_HOST", '127.0.0.1')
ast_port = int(os.getenv("AST_ARI_PORT", 8088))
ast_url = os.getenv("AST_URL", 'http://%s:%d/'%(ast_host,ast_port))
ast_username = os.getenv("AST_USER", 'user-here')
ast_password = os.getenv("AST_PASS", 'password-here')
ast_app = os.getenv("AST_APP", 'v')


model = vosk.Model('vosk-model-pt-fb-v0.1.1-20220516_2113/')
#model = vosk.Model(lang='en-us')
channels = {}

class Channel:

    async def rtp_handler(self, connection):
        async for message in connection:
            data = array.array('h', message[12:])
            data.byteswap()
            if self.rec.AcceptWaveform(data.tobytes()):
                res = self.rec.Result()
            else:
                res = self.rec.PartialResult()
           print(res)

    async def init(self, client, channel):
        self.port = 45000 + len(channels)
        self.rec = vosk.KaldiRecognizer(model, 16000)
        self.udp = aioudp.serve("127.0.0.1", self.port, self.rtp_handler)
        await self.udp.__aenter__()

        bridge = await client.bridges.create(type='mixing')
        media_id = client.generate_id()

        # Alterando para _apps
        await client.channels.externalMedia(channelId=media_id, app=client._apps, external_host='127.0.0.1:' + str(self.port), format='slin16')

        await bridge.addChannel(channel=[media_id, channel.id])

async def statis_handler(objs, ev, client):
    channel = objs['channel']
    channel.answer()
    if 'UnicastRTP' in channel.name:
         return

    local_channel = Channel()
    await local_channel.init(client, channel)
    channels[channel.id] = local_channel

async def main():
     async with asyncari.connect(ast_url, ast_app, ast_username, ast_password) as client:
         async with client.on_channel_event('StasisStart') as listener:
             async for objs, event in listener:
                  await statis_handler(objs, event, client)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    anyio.run(main)

I would like some guidance as to whether it is possible to transcribe the customer’s leg after going through the queue application?

Hi. Not sure what the problem is but you can use spoofing channel to select only customer. Something like

        # First create snooping channel and put it into a snooping bridge
        await client.channels.snoopChannelWithId(app=client._app, appArgs='snooping', channelId=channel.id, snoopId = channel.id + "_snoop", spy="in")
        snoop_bridge = await client.bridges.create(type='mixing')
        await client.channels.externalMedia(channelId=channel.id + "_media", app=client._app, external_host='localhost:' + str(self.port), format='slin16')
        await snoop_bridge.addChannel(channel=[channel.id + "_media", channel.id + "_snoop"])

        # Dial out and create second bridge
        outgoing_channel = await client.channels.originate(endpoint="PJSIP/1002", app = client._app, appArgs = "dialed")

        await client.channels.snoopChannelWithId(app=client._app, appArgs='snooping', channelId=outgoing_channel.id, snoopId = outgoing_channel.id + "_snoop", spy="in")
        snoop_bridge = await client.bridges.create(type='mixing')
        await client.channels.externalMedia(channelId=outgoing_channel.id + "_media", app=client._app, external_host='localhost:' + str(self.port + 1), format='slin16')
        await snoop_bridge.addChannel(channel=[outgoing_channel.id + "_media", outgoing_channel.id + "_snoop"])

        # Bridge calls
        main_bridge = await client.bridges.create(type='mixing')
        await snoop_bridge.addChannel(channel=[channel.id, outgoing_channel.id])

The dial plan used works when calling number 4 of an extension, I don’t know how to run Stasis after an agent has been answered using a service queue.

One question, to transcribe the customer’s leg after being served in the queue, the queue logic must be within the stasis code or can I call stasis through the standard queue application via dial plan?

I was successful in transcribing the attendant’s leg using Queue():

  • gosub - Will run a gosub on the called party’s channel (the queue member) once the parties are connected. The subroutine execution starts in the named context at the s exten and priority 1.

However, the call remains silent, I believe Stasis is overriding the queue call.

Reading the blog article A Bridge Too Far ⋆ Asterisk the ideal would be:

Each call participant can potentially have their own service attached via audiohook independent of the channels created via queue, has anyone already done something in this regard?