Friday, March 16, 2012

Asterisk Text-To-Speech Cepstral Setup

Text To Speech Integration
Cepstral + Asterisk

I've been holding onto this post for sometime, wanted to post it with some cool experiment like an IVR based story line which narrates the story and changes the story line according to choices made by listener(DTMF based and then later on Speech Recognition based).

I've now realized that due to extremely busy schedule at job and home I may not get any extra time to make a sample story; insert it into the MySQL DB; make a dialplan for it; create its web end to manage/edit stories and present it here. So instead of delivering it all in one piece its better to take a start from giving our Asterisk server a voice by installing Cepstral TTS engine.

Following are the commands to get going.

Download and Install Cepstral TTS Engine.


#tar zxvf Cepstral_Callie-8kHz_i386-linux_5.1.0.tar.gz

#cd Cepstral_Callie-8kHz_i386-linux_5.1.0


Download and Install App-Swift.
App_swift is the connector between the asterisk and Cepstral engine.Swift runs from inside asterisk as an application and uses the Cepstral TTS engine running in Linux.

#cd /usr/src/


#tar zxvf app_swift-1.6.2.tar.gz

#cd app_swift-1.6.2/


#make install

Issue this command to let Cepstral recognize the Swift module and let it use its engine.
#echo /opt/swift/lib > /etc/


Thats it and now your TTS engine and Asterisk app_Swift connector should be ready to rock

Test Asterisk for Swift Application.
Now test Asterisk for swift application; On CLI execute the following command
Asterisk*CLI>core show application swift

You should get some long output like below:

-= Info about application 'Swift' =-

Speak text through Swift text-to-speech engine.

Swift(text) Speaks the given text through the Swift TTS engine.
Returns -1 on hangup or 0 otherwise. User can exit by pressing any key.

Make Dialplan to speak something for you. 

exten => 1234,1,NOOP(--Starting Text-To-Speech Test--)
same => n,Answer()
same => n,Swift(Hello World This is an Asterisk server)
same => n,NoOp(Key pressed: ${SWIFT_DTMF})
same => n,Swift(You pressed ${SWIFT_DTMF}. Goodbye.)
same => n,Hangup()

exten => h,1,Hangup()

Thats all, now make your own dialplan and enjoy talking to your asterisk server. Best thing for Forever Alone guys ;)


Tuesday, March 6, 2012

Making RTPproxy work

Kamailio + RTPproxy  

In response to my previous post related to Kamailio as SBC for Media-Servers, I'm often asked to show how to make this whole setup work with RTPproxy. That means a successful two-way audio call. Remember that the original configuration found on Asipto-Blog is for Public-IPs only.

I had to do alot of hit-&-trial sort of testings with my configuration before making the configurations work for me, so I'll share all that I remember now.

UPDATE: Another new version of this page is available here.

STEP-I : Starting RTPproxy:
Start RTPproxy in bridging mode.

#/usr/sbin/rtpproxy -F -s udp: -l PU.BL.IC.IP/ -d DBUG:LOG_LOCAL0
STEP-II: Kamailio Configuration file:
Define RTPproxy controller port in modparams area.

#RTPproxy instance to be used: 7722 
modparam("rtpproxy", "rtpproxy_sock", "udp:") 

Then in route[RTPPROXY] we need to know if the call is coming from WAN/internet side or from  LAN/Private Asterisk's side so I had to put the following lines in modparams area as well for DB connectivity. This is required to query the dispatcher tables in RTPPROXY route.

# ------- AVP-OPS params ---------
modparam("avpops","db_url", DBURL)

So finally in the route for RTPproxy we querry the DB table dispatcher for inbound or oubound call requests from/to media-servers.

# RTPProxy control
route[RTPPROXY] {
#!ifdef WITH_NAT
 xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY]\n");
 if (is_method("BYE")) {
  xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY] unforced RTP Proxy STATS='$rtpstat'\n");
 } else if (is_method("INVITE")){
  if(avp_db_query("select destination from dispatcher where destination like '%$dd%'")){
   xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in route[RTPPROXY] RTPproxy with IE Flags\n");
  else if(avp_db_query("select destination from dispatcher where destination='sip:$si:$sp'")){
   xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in route[RTPPROXY] RTPproxy with EI Flags\n");

    xlog("L_NOTICE","$rm from $fu (IP:$si:$sp) in Route[RTPPROXY] Forcing RTPproxy\n");

 if (!has_totag()){ 

RTPproxy Bridging Network Scenario
Please note that the order of I and E flags. The sequence of these flags depends on the rtpproxy running in the background and the order of PUBLICIP and PRIVATEIP while starting RTPproxy.
#/usr/sbin/rtpproxy -F -s udp: -l PU.BL.IC.IP/ -d DBUG:LOG_LOCAL0

The flags sequence can get inverted if I execut rtpproxy like this.Note the order of Public Ip and Private IP.
#/usr/sbin/rtpproxy -F -s udp: -l -d DBUG:LOG_LOCAL0

Once done changes in configurations file save it and restart kamailio. Make sure Kamailio detects the RTPproxy socket and announces that support for Rtpproxy is enabled.

Make calls and see the RTPproxy stats at the end of each call. 

Troubleshooting Tips:

Use "tcpdump" on Kamailio server and trace ALL the traffic on ALL the interfaces i.e WAN+LAN interfaces using the following command.

#tcpdump -i any -s 0 -w SIP-TRACE.pcap -vvvv

Once a call is completed stop the trace by hitting CTRL+C; download the pcap file to your windows desktop; open the file in wireshark; analyse VoIP call and see the flow of packets between caller and callee.Reading and understanding SIP/SDP INVITEs packets between caller to Kamailio and then from Kamailio to Media-server is very critical in understanding why we are having no-audio or one-way-audio for  a bad call.

Thats all for now,I'm thinking of exploring Media-Proxy as well. I hope someday I'll post about it too.