Sending RTP packets during silence

Hello,

Callers to our Asterisk using a particular phone system are experiencing issues with cut off audio - the start of prompts played to the caller following a period of silence are clipped off.

Investigating the issue further, our VOIP provider has diagnosed this as follows:


After further investigating this issue internally, we have been advised that the issue is due to you “muting” the RTP stream from your side. Having this setup like you do with the “mute” happening will definitely cause bad audio quality, dropped packets, etc. In the attached call sample you provided us, the number of packets from us to your network is 1449 while the number of packets from your network to us is 450. To fix this issue, you need to at least send empty RTP packets when no one is talking, not just stop the whole RTP stream from your end.


We do not explicitly “mute” anything as far as I am aware.

I’ve tried this in asterisk.conf:
transmit_silence = yes

And this in sip.conf:
rtpkeepalive=1

But neither seemed to solve it. Do any other solution spring to mind ?

Thank you in advance for your help,
Regards,
Mark

So wasteful. :confused:

What’s output of “rtp set debug on” from your Asterisk CLI ? Maybe you are sending but something along the way is dropping out eg. flaky firewall ?

That’s deprecated chan_sip – new way is chan_pjsip – might be you get more help here by upgrading Asterisk, first.

Hello, thanks for your reply, I agree, it does seem wasteful, but I can’t get the upstream providers to change unfortunately.

I used a packet scanner at my end, and one at the receiving end, and no rtp replies were present during silence, so I’m reasonably sure Asterisk is not sending. Should it be, or is Asterisk behaving as intended?

I’m probably using pjsip (how do I check) - I had also tried this in pjsip.conf:

rtp_keepalive=1

I set “rtp set debug on” as you suggested and during the period of silence I see a lot of sequential

Got RTP packet from…

but no

Sent RTP packet to…

At the point it is doing this I am doing some processing (in FastAGI) which takes about 3 seconds. Hence the silence. Then when the processing is done and I play the next prompt I can see the “Sent RTP packet to…” begin again.

Is there a way to make Asterisk reply with empty packets when it receives them?

If so, will there be a performance hit with many concurrent calls?

Is it even a reasonable request from the upstream provider - should I try pushing back and say it’s fine not to send any packets during silence? I would need somewhere to point them to that confirms this I think.

Thanks again,
Mark

Hi - I added it back to pjsip.conf and I can see in the logs in amongst the Got RTP packets:

Sent Comfort Noise RTP packet to IP:15662 (type 02, seq 018403, ts 127521, len 000001)

Sent Comfort Noise RTP packet to IP:15662 (type 02, seq 018404, ts 127521, len 000001)

Sent Comfort Noise RTP packet to IP:15662 (type 02, seq 018405, ts 127521, len 000001)

It seems to be every 2 seconds rather than 1 - but that may just be the logs on the screen catching up. So I looked at ts to verify and it looks to be the same for each consecutive comfort noise which seems wrong?

When I’m sending RTP type 08 packets, ts increments with time. But with comfort noise it does not seem to.

The next time comfort noise starts, ts seems correct on the first one (incremented) but again subsequent ones aren’t incremented:

Sent Comfort Noise RTP packet to IP:15662 (type 02, seq 018549, ts 256322, len 000001)

Sent Comfort Noise RTP packet to IP:15662 (type 02, seq 018550, ts 256322, len 000001)

Any ideas ?

Regards,
Mark

RTP isn’t required to be continuous and Asterisk is acting just fine.

On the Asterisk CLI run “core show channels” and see if anything says PJSIP or is it all plain SIP ?

There are perhaps better ways to handle that, such as Stasis() application, newer (version 20+) Signal()/WaitForSignal() applications, etc.

Yes, but it is probably harder with FastAGI() than newer methods/apps/flows.

As long as you are not transcoding, then it should not be a significant hit.

Or, should you try another provider who thinks it is fine (which is probably the majority) ?

That seems RFC3389 compliant, per sections 4 & 5 (highlights below):

The RTP header for the comfort noise packet SHOULD be constructed as if the comfort noise were an independent codec. Thus, the RTP timestamp designates the beginning of the comfort noise period.

For example, the CN packet may be sent periodically or only when there is a significant change in the background noise characteristics.

RTP allows discontinuous transmission (silence suppression) on any audio payload format.

How about creating a thread to inform the caller while you do your processing in main?

For example:

  1. Create a thread to play ‘Please hold while we process your credit card and get ready for a wild ride.’
  2. Auth the card in main.
  3. Join the prompt thread.
  4. Keep calm, carry on.

What methods/apps/flows are you referring to?

That sounds like a nice way to do it – a potentially non-blocking approach to AGI.

Stasis() with Asterisk REST API was mentioned, as a way to avoid dial plan flow.

Conversely, to go all in on dial plan, another method in newer Asterisk versions 20+ with Signal()/WaitForSignal() apps could be to StartMusicOnHold() before entering WaitForSignal() after asynchronously Originate()'ing a call to a Local context that does the slow 3 second processing and sends a unique Signal() with the result (and return code) that the caller is WaitForSignal()'ing on – add in some CURL() function and it might never need to leave the dial plan.

Hi All,

Thank you for your help and thoughts.

The line is a complex speech recognition app - it’s been working fine for years with no issues until this particular system, so we’re ideally looking for a minimal change solution.

I had thought, as suggested above, about asynchronously carrying out the processing, and playing 100ms of silence repeatedly until processing had finished, however I discovered another case where prompts were being clipped:

  • If we ask a question and listen for caller input in the MRCPRecog state
  • then if the caller stays silent, we wait 4 seconds and play a “Sorry I didn’t hear” you prompt
  • On the system with the issues, the “Sorry” is cut off - because again we were not sending anything while we are listening.

There may be others, so I was hoping the “comfort noise” solution would work. This is still being investigated at their end - and apparently depends on who the call is routed through, so there’s hope it might be solved at their end.

For now I will report to them your comments about RTP not requiring to be continuous, and the timestamps on the Comfort Noise being correct, and hopefully they will be able to sort it out upstream of us.

Thanks Again,
Mark

Hello,

You need to ask your voice provider to cancel the VAD (Voice Activity Detection) and noise suppression on your trunks. The Asterisk does not support VAD at all. If it does not work, try to switch to another provider without VAD support.

Thank you,

Daniel Friedman
Trixton LTD

Just a note that you’re using an outside module, so how it behaves is up to it. For example transmit_silence may have no effect on it, while for core things it does.

I really don’t understand why is it so difficult to answer the simple OP question: Is there a way to make Asterisk send RTP packets when there is silence. Yes or no. And if yes please kindly show how.

Because Asterisk doesn’t control the implementation detail of outside modules. If you are recording audio, for example, and transmit_silence is set to yes then we transmit silence. Does that mean the outside module behaves the same way? No.

Thanks Jcolp, actually on re-reading the thread I realized the OP is actually able to get Asterisk to send silence packets. Got it.

Thanks all. By outside modules are you referring to MRCPRecog ? So as I understand it, that then takes full control, and there is no general setting I can change to transmit silence when it is in effect?

And Agi ? Should transmit_silence = yes cause silence to be transmitted while it is within the service method, but not actually doing anything proactive on the line e.g. not invoking streamFile / Record etc - at that point it’s just trying to work out what it needs to do next.

As mentioned above, one option is that I should be able to do the processing asynchronously and send repeated short duration silences with streamFile until it’s finished. MRCPRecog is outside my control though so not sure I could fix that example.

Having investigated further, it seems someone in the chain is updating the RTP timestamp immediately after the period of silence to be 160ms after the prior one, rather than the actual 5 seconds of silence. We’re still looking into who is doing that and why.

If MRCPRecog is invoked, it has control. As for AGI I believe transmit_silence only applies when certain operations are done - such as recording. It is not a blanket all the time thing.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.