Routing RTP Between SIP Channels via External RTP/UDP Server

Hello community,

I am new to both this community and to Asterisk. I am currently working on building an Asterisk ARI-based application using the ari4java library on Asterisk 18.10.

The primary goal of my project is to route RTP packets during a SIP call through an external RTP/UDP server rather than having them exchanged directly within a bridge. The external media server will process the RTP packets and return them to their destination. Please refer to the following image for a visual representation:

I manage the call state from my ARI application. When SIP2 answers the call, I create an external media channel and a mixing bridge, then move my other SIP channels to the new bridge. This setup allows me to receive RTP packets on the external media server. However, the problem I am encountering is that when I enable RTP debug, I find that the packets are not passing in the correct sequence order as I expect via the external media.

I am unable to determine the root cause of this issue. Could you please provide any ideas or references that might help solve my problem? Below, I have shared some commands and logs for your better understanding.

Thank you for your kind attention.

POST /ari/channels/externalMedia?app=comprehensive-app&external_host=10.11.106.117%3A8765&format=ulaw HTTP/1.1
content-type: application/json
content-length: 53
host: 10.11.106.117
connection: close
authorization: *****

{"variables":{"PJSIP_DIAL_CONTEXT":"external_media"}}
{"type":"StasisStart","timestamp":"2024-06-06T20:37:38.030+0600","args":[],"channel":{"id":"1717684658.2","name":"UnicastRTP/10.11.106.117:8765-0x7f12e800e060","state":"Up","caller":{"name":"","number":""},"connected":{"name":"","number":""},"accountcode":"","dialplan":{"context":"default","exten":"s","priority":1,"app_name":"Stasis","app_data":"comprehensive-app"},"creationtime":"2024-06-06T20:37:38.030+0600","language":"en"},"asterisk_id":"d8:5e:d3:7d:c9:d0","application":"comprehensive-app"}

Here is configuration of my pjsip_user.conf

[7001](voice_changer_defaults)
aor/max_contacts = 5
;aor/max_contacts = 1
endpoint/callerid = 7001
inbound_auth/username = 7001
inbound_auth/password = 1234
direct_media=no
media_address=10.11.106.117
media_port=8765

[7002](voice_changer_defaults)
aor/max_contacts = 5
;aor/max_contacts = 1
endpoint/callerid = 7002
inbound_auth/username = 7002
inbound_auth/password = 1234
direct_media=no
media_address=10.11.106.117
media_port=8765

Here is configuration of my pjsip_wizard.conf

[voice_changer_defaults](!)
type=wizard
transport = transport-udp
accepts_registrations = yes
sends_registrations = no
accepts_auth = yes
sends_auth = no
endpoint/context = voice_changer
endpoint/dtmf_mode = rfc4733
endpoint/call_group = 1
endpoint/pickup_group = 1
endpoint/language = ja
endpoint/disallow = all
endpoint/allow = ulaw
endpoint/rtp_symmetric = yes
endpoint/force_rport = yes
endpoint/direct_media = no
;endpoint/media_address=10.11.106.117
;endpoint/media_port=8765
endpoint/send_pai = yes
endpoint/send_rpid = yes
endpoint/rewrite_contact = yes
endpoint/inband_progress = yes
endpoint/allow_subscribe = yes
endpoint/transport = transport-udp
aor/max_contacts = 1
aor/qualify_frequency = 60
aor/authenticate_qualify = no

Here is configuration of my extensions.conf

[voice_changer]
exten => 7001,1,NoOp(Voice Changer Example by SIMEC)
same => n,Answer()
same => n,Stasis(comprehensive-app)
same => n,Goto(ari-${STASISSTATUS},1)

exten => 7002,1,NoOp(Voice Changer Example by SIMEC)
same => n,Answer()
same => n,Stasis(comprehensive-app)
same => n,Goto(ari-${STASISSTATUS},1)

; ARI Success / Failure
exten => ari-SUCCESS,1,Hangup()
exten => ari-FAILED,1,Playback(sorrydave)
exten => ari-FAILED,2,Hangup()

;exten => _X.,1,Dial(SIP/external-mediaserver)
;exten => _X.,1,Dial(PJSIP/s)


[external_media]
exten => s,1,NoOp(External Media Channel Started)
same => n,Stasis(comprehensive-app)
same => n,Hangup()

here is the log of my asterisk console

    -- Executing [7001@voice_changer:1] NoOp("PJSIP/7002-00000000", "Voice Changer Example by SIMEC") in new stack
    -- Executing [7001@voice_changer:2] Answer("PJSIP/7002-00000000", "") in new stack
       > 0x7f6de8019790 -- Strict RTP learning after remote address set to: 10.11.105.4:4000
    -- Executing [7001@voice_changer:3] Stasis("PJSIP/7002-00000000", "comprehensive-app") in new stack
       > 0x7f6de8019790 -- Strict RTP switching to RTP target address 10.11.105.4:4000 as source
    -- Channel PJSIP/7002-00000000 joined 'simple_bridge' stasis-bridge <3e5ea3e4-0263-4e90-806d-194da6dfbc1f>
    -- Called 7001
    -- PJSIP/7001-00000001 is ringing
       > 0x7f6de8024ad0 -- Strict RTP learning after remote address set to: 103.192.157.228:8000
       > 0x7f6de8024ad0 -- Strict RTP qualifying stream type: audio
    -- PJSIP/7001-00000001 answered
       > Launching Stasis(comprehensive-app,me) on PJSIP/7001-00000001
[2024-06-07 00:37:15] WARNING[73202]: res_pjsip_pubsub.c:3492 pubsub_on_rx_publish_request: No registered publish handler for event presence from 7001
[2024-06-07 00:37:15] WARNING[73202]: res_pjsip_pubsub.c:804 subscription_get_handler_from_rdata: No registered subscribe handler for event presence.winfo from 7001
    -- Channel PJSIP/7001-00000001 joined 'simple_bridge' stasis-bridge <3e5ea3e4-0263-4e90-806d-194da6dfbc1f>
       > Bridge 3e5ea3e4-0263-4e90-806d-194da6dfbc1f: switching from simple_bridge technology to native_rtp
       > Locally RTP bridged 'PJSIP/7001-00000001' and 'PJSIP/7002-00000000' in stack
       > 0x7f6e40003200 -- Strict RTP learning after remote address set to: 10.11.106.117:8765
    -- Called 10.11.106.117:8765
    -- UnicastRTP/10.11.106.117:8765-0x7f6e40002660 answered
       > Launching Stasis(comprehensive-app) on UnicastRTP/10.11.106.117:8765-0x7f6e40002660
       > 0x7f6de8024ad0 -- Strict RTP learning after remote address set to: 103.192.157.228:8000
[2024-06-07 00:37:15] WARNING[73202]: res_pjsip_pubsub.c:3492 pubsub_on_rx_publish_request: No registered publish handler for event presence from 7001
[2024-06-07 00:37:15] WARNING[73202]: res_pjsip_pubsub.c:804 subscription_get_handler_from_rdata: No registered subscribe handler for event presence.winfo from 7001
       > 0x7f6de8024ad0 -- Strict RTP switching source address to 10.11.105.4:8000
    -- Channel UnicastRTP/10.11.106.117:8765-0x7f6e40002660 joined 'simple_bridge' stasis-bridge <4dedfc4c-d7eb-4d24-9384-e0267f92d269>
    -- Channel PJSIP/7002-00000000 left 'native_rtp' stasis-bridge <3e5ea3e4-0263-4e90-806d-194da6dfbc1f>
       > Bridge 3e5ea3e4-0263-4e90-806d-194da6dfbc1f: switching from native_rtp technology to simple_bridge
    -- Channel PJSIP/7002-00000000 joined 'simple_bridge' stasis-bridge <4dedfc4c-d7eb-4d24-9384-e0267f92d269>
       > 0x7f6e40003200 -- Strict RTP switching to RTP target address 10.11.106.117:8765 as source
    -- Channel PJSIP/7001-00000001 left 'simple_bridge' stasis-bridge <3e5ea3e4-0263-4e90-806d-194da6dfbc1f>
    -- Channel PJSIP/7001-00000001 joined 'simple_bridge' stasis-bridge <4dedfc4c-d7eb-4d24-9384-e0267f92d269>
       > Bridge 4dedfc4c-d7eb-4d24-9384-e0267f92d269: switching from simple_bridge technology to softmix
       > 0x7f6de8019790 -- Strict RTP learning complete - Locking on source address 10.11.105.4:4000
  == Endpoint 201 is now Reachable
    -- Contact 201/sip:201@10.11.106.117:56638;rinstance=c921d640027fa9c8 is now Reachable.  RTT: 0.780 msec
       > 0x7f6e40003200 -- Strict RTP learning complete - Locking on source address 10.11.106.117:8765
       > 0x7f6de8024ad0 -- Strict RTP learning complete - Locking on source address 10.11.105.4:8000

You can’t do this in a single bridge, with a single external media channel. You would need to have multiple and have them be independent, with the ARI application effectively having its own internal media forwarding.

As it is by having all channels in the same bridge they’ll all get the respective mixed audio.

1 Like

Thank you for your response and guidance in resolving my issue. As I’m relatively new to Asterisk, it’s not easy for me to tackle this. I followed your suggestions and adjusted my process accordingly, as depicted in the image below.

I achieved the desired outcome, thanks to your help. I’m hopeful that I can continue learning and working with Asterisk. Thank you once again.