Executing Async AGI or EAGI on Bridged Channels (also tried ChanSpy)

Hi All - I am fairly new to Asterisk and have been writing an EAGI script that pushes audio from a channel into a .wav file for recording purposes. I currently have this script working but have a problem where the EAGI fails after the call is bridged. I have tried a few different solutions and none of them are currently working - here have been my attempts.

  1. Working on 2 independent channels before Bridging
  • User calls toll-free trunk number
  • Extension rings softphone
  • Two copies of the EAGI run independently but channels have not been bridged so users can’t hear one another
  1. Applying Async AGI to each Channel
  • I’ve tried using Async AGI to invoke the EAGI script after the bridge but from what I can tell once the channels are bridge the Async AGI nolonger works on the channels until they exit the bridge
  1. Apply ChanSpy to an individual channel after the calls are bridge, duplicating the audio on a new channel
  • Basically I create a duplicate channel that taps into one of the bridged channels and try to execute the EAGI script on that new channel
  • This also fails as soon as the ChanSpy is initiated

My manager frustration here is with Bridging… from what I can understand the EAGI scripts and Async AGI (using AMI) work perfectly when the channels are NOT bridged but the second the channels are bridged they are unresponsive or exit the existing EAGI call that is running. So my main question here is:

  1. How can you bridge two channels without exiting the Async AGI on each channel
  2. How can you connect 2 channels (so they caller and receiver can hear one another) without breaking these channels. I know when you bridge there are /Surrogate channels that are created but from what it looks like you can’t execute commands on these channels themselves.
  3. When you bridge a call do the original channels that you bridge still remain entirely independent? Is the audio of each speaker isolated to that channel or can you here the other speaker’s audio in each independent channel.

Sorry for all of the questions at one, if someone has some better comprehensive understanding of Asterisk I would appreciate your thoughts. Have spent probably 20 hrs playing around with these different options and from I understand it doesn’t seem like there is any way to run EAGI or Async AGI on channels once they have been bridged - bridging basically kills functionality to an individual channel.

Why aren’t you using MixMonitor? It’s audio hooks inherit across the masquerade, whereas using Bridge is likely to generate a masquerade and replace the channel running AGI.

I’m not really familiar with MixMonitor - I will look it up. I’m guessing it can be used to join two channels without replacing them? If you have any example via extension call I would appreciate it. What exactly does it do?

Looking at MixMonitor it looks like it is specifically for saving audio from a channel to a file. This doesn’t really solve the issue of executing EAGI or AGI scripts on an audio channel once they are bridged. Is there an alternative to briding? Is it just impossible to execute EAGI or AGI on a channel once it is bridged?

Kind of confused here because seems like there is so much you can do with a channel but then the second its bridged to another everything else fails. If this is true - are there any other ways to connect two channels without briding them?

Note: I would be nice to keep each channel recording separate - this is why I was trying to execute an EAGI on each call independently instead of recording them simultaneous on the same bridge channel.

No, bridging is the act of connecting channels together so media is exchanged. You also fundamentally can’t do two things on a channel at once. That is: You can’t execute an AGI on a channel and also have it in a bridge. That would have two “owners” on a channel and would conflict with each other. ChanSpy would be the way to go, but due to the way that the Bridge action works it may not carry over. What version of Asterisk are you using? Another option would be to send them to a ConfBridge and then originate a Local channel which executes the AGI, but this would give you the combined audio from both channels.

I am using AsteriskNow 13. The AGI and EAGI functionality is great - especially the ability to execute commands asynchronously post channel creation but I really don’t understand the point of this if you can’t do it once the channel is connected to another party. This means you can only talk to the channel when it is independent?

I tried executing on the /Surrogate channels but it returns that they are “dead” channels. I tried the ChanSpy using a duplicate channel just to listen in on one of the bridged channels - it works but the second you execute the ChanSpy you are unable to execute any Asynchronous commands to the channel “listening in” on another channel.

I will give it a try with ConBridge but I’m puzzled this is such a problem. My hope was to execute the bridge from inside of the EAGI or AGI script but either way I think it destroys the connection to the original channel as you mentioned - only one owner allowed per channel and once the channel is invoked for a Bridge or ChanSpy for that matter you lose all control over it.

That’s correct, AGI and EAGI is not for third party arbitrary call control and interaction. It’s an interface to something else to execute things on the channel.

You can’t ChanSpy on Surrogate channels as they are ephemeral and part of the process by which Bridge works. You could use Originate to execute ChanSpy on the channel and send the other half into the dialplan where you can execute AGI/EAGI. That effectively copies the media stream and directs it elsewhere to another channel.

AMI is one way of providing third party control, but it does not give you access to the media, except in as much as you can use it to set up MixMonitor.

Lots of people find AGI useful, even without the ability to survive a bridge. Some may use it because they are uncomfortable with dialplans as a programming language, but I think many use it because it provides richer ways of interacting with databases and other external applications.

@david551 Sure that makes a ton of sense - but I guess the question is… can you only use Async AGI on calls that are a single channel? Is there any way to have a two channel (actual conversation) without losing the AsynAGI ability?

So either:

  1. use alternative way to bridge channels without killing AsyncAGI access
  2. give up AsyncAGI access to be able to have a 2 party call?

Note: I did try out MixMonitor and it appears the call quality of the .wav is way superior to my previous access through EAGI. Can you use MixMonitor on two channels independently?? that would be perfect

MixMonitor can be used on any channel, including channels that are bridged. If you don’t want both directions of audio though you need to use the options MixMonitor provides to limit the direction.

This is interesting - but I’m not sure what you mean. I tried doing ChanSpy on one of the bridged calls and when you ChanSpy the call that is in the bridge into another channel that is not - you lose the AGI control over the call “listening in” on the other call. Perhaps here it matters which order you execute them in - but from what I see if you start the EAGI on the “listening in” call prior to it “listens” then as soon as the ChanSpy start it kills the EAGI. If you do the ChanSpy before initiating the EAGI then you lose AGI ability over the “listening in” channel once the ChanSpy starts.

You’re going to need to be specific on what channels you are referring to. Thinking about it more you’d do an Originate to a Local channel that executes Answer and then ChanSpy() on the channel to spy on. Then to the Originate action you’d tell it to execute the EAGI on answer. That effectively copies the media stream and creates another channel that can be controlled. People use that now with whisper to inject arbitrary media to channels.

Ultimately though if you strictly need recording MixMonitor is the best option.

Do you have any example of how you would do it on the channels independently? Examples show it being invoked before calling the other party.

exten => _.,1,Answer()
exten => _.,2,MixMonitor(test.wav)
exten => _.,3,Dial(PJSIP/****)
exten => _.,4,Hangup()

Yea - I was really impressed with the audio quality of MixMonitor - sounds far superior to the EAGI recording for some reason. If you have any advice on invoking it on independent channels would appreciate it. Thanks for hanging out online - been very helpful!

That executes MixMonitor on the calling channel. If you wanted it on the called channel you’d use a pre-dial handler[1].

[1] https://wiki.asterisk.org/wiki/display/AST/Pre-Dial+Handlers

You give it the name. You decide. The CHANNEL[1] dialplan function can also give tons of info, as well as CALLERID[2] for the callerid information.

[1] https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Function_CHANNEL
[2] https://wiki.asterisk.org/wiki/display/AST/Asterisk+13+Function_CALLERID

My question was more on how to concatenate info from the invoker and concatenate it in the parameters of the text. So like before I could make an extension that calls MixMonitor on each channel independently but would need the files to be named differently or else both channel would write to the same file. So something like this:

exten => _.,1,Answer()
exten => _.,2,Dial(PJSIP/****,G(record-call,1),)

exten => _.,1,Answer()
exten => _.,2,MixMonitor(${CHANNEL(pjsip,call-id)}.wav)

Just not sure if you can concatenate like that. Also - when I invoked it like this before it appeared that the channels are not bridged.

You can’t Answer in there. That will break things. Otherwise it would work.

******* Example *******

So I tried out what you recommended using the example on the caller (B) and not the callee (b) but both channels of audio are still getting recorded. Are you sure that MixMonitor can record independent channels? It looks like the correct channel is going to the MixMonitor (not both) but both channels are still recorded. Another problem is I need to be able to call it on both the caller and callee independently - this is why I was using G before. Is there a way to execute bother B and b?? Guess it won’t matter if there is no way to really separate the channels.

*** Help? Need to invoke both B and b for caller and callee? How to actually record separate channel on MixMonitor? ***
exten => _.,1,NoOp()
same => 2,Dial(PJSIP/1000,B(custom-answer^caller_handler^1))
same => 3,Hangup()

exten => caller_handler,1,NoOp()
same => n,Verbose(0, In caller pre-dial handler!)
same => n,MixMonitor(${CHANNEL}.wav)
same => n,Return()

exten => callee_handler,1,NoOp()
same => n,Verbose(0, In callee pre-dial handler!)
same => n,MixMonitor(${CHANNEL}.wav)
same => n,Return()

SIP Debugging Disabled
== Using SIP RTP TOS bits 184
== Using SIP RTP CoS mark 5
– Executing [@custom-answer:1] NoOp("SIP/-00000001", “”) in new stack
– Executing [@custom-answer:2] Dial("SIP/-00000001", “PJSIP/1000,B(custom-answer^caller_handler^1)”) in new stack
– SIP/-00000001 Internal Gosub(custom-answer,caller_handler,1) start
– Executing [caller_handler@custom-answer:1] NoOp("SIP/
-00000001", “”) in new stack
– Executing [caller_handler@custom-answer:2] Verbose(“-00000001", “0, In caller pre-dial handler!”) in new stack
In caller pre-dial handler!
– Executing [caller_handler@custom-answer:3] MixMonitor("SIP/
-00000001”, “SIP/-00000001.wav") in new stack
– Executing [caller_handler@custom-answer:4] Return("SIP/
-00000001”, “”) in new stack
== Spawn extension (custom-answer, , 2) exited non-zero on 'SIP/-00000001’