Archive for June, 2011

Fallback to text to speech if your audio fails

Tuesday, June 28th, 2011

Here’s a quick tip that’s an answer to a common question: What happens if my audio file cannot be played?

If you provide the URL to an audio file in Tropo’s say function Tropo will fetch it and play it. But what if you have a mistake in your URL? Or your server is down? You can use the W3C standard SSML to provide a text to speech (TTS) fallback and prevent your callers from getting dead air.

Say you have an application that starts out like this:

<?php
say('http://example.com/welcome.wav');
?>

Tropo will play welcome.wav if it can reach the file.

Now I’ll use a little SSML to provide a TTS string to play if your file isn’t available:

<?php
say('<speak><audio src="http://example.com/welcome.wav">This text will be spoken if the audio file can not be played.</audio></speak>');
?>

Just another example of how Tropo makes the easy stuff easy while still making it possible to do most anything.

Telephony Black Magic with Tropo, Node.js and Redis

Tuesday, June 28th, 2011

In a previous post and screencast on this blog, I demonstrated an example application that highlights some of the more unique features of Tropo to support realtime applications.

Tropo’s unique ability to write to, and read from persistent socket connections during the execution of a call sets it apart from other platforms, and creates opportunities to do things that other platforms can only dream of.

In this screencast, I build upon and extend my earlier example using Redis, Node.js and jQuery to allow a user to inject text into a running Tropo session and have it read out over the phone using Text-to-Speech.

Here is an overview of the technical components of this example application (opens in new window).

What I get really excited about in this demo application – the code for which can be found on GitHub – is the ability to send TTS output to multiple subscribers. Redis’ PubSub functionality will send a message published on a channel to all subscribers, so if you have multiple people called in to your app, every one of them will get the message sent from a single publisher.

How cool is that?!?

if you’re building a realtime application that requires voice, SMS or IM functionality, look no further than the Tropo platform.

With Tropo and powerful tools like Redis and Node.js, you can make telephony black magic.

Have fun!

Building a full-featured conference call application with Tropo and PHP

Friday, June 24th, 2011

Tropo’s conference function makes it easy for you to join multiple callers onto a single call together. One line of code and you have a conference call…

<?php conference('someid'); ?>

That’s it. A basic conference line. Use that as your application and everyone calling into your number will be joined into a single conference call. How many users? By default, Tropo allows up to 100 users into a single conference. We can do more if you need it, but you might want to think through your use case a bit first. 100 people all talking on one line gets crazy fast.

Now let’s take this basic concept and turn it into a full-fledged application. Our requirements for the conference call start with allowing the entry of a conference ID so that this number can be used for more than one call.

<?php
$response = ask('Enter your conference ID', array(
    'choices' => '[4 DIGITS]'
));
conference($response->value);
?>

We’d also like to allow conference IDs of multiple lengths (instead of just 4 digits), and to let the caller tell us when they’re done with entry by pressing #. How about conference IDs of 3-10 digits?

<?php
$response = ask('Enter your conference ID. Press the pound key when finished.', array(
    'choices' => '[3-10 DIGITS]',
    'terminator' => '#'
));
conference($response->value);
?>

In noisy rooms offices, background noise sometimes get misinterpreted as input. Since we’re only accepting numeric conference IDs, let’s turn off speech recognition and restrict input to the keypad

<?php
$response = ask('Enter your conference ID. Press the pound key when finished.', array(
    'choices' => '[3-10 DIGITS]',
    'terminator' => '#',
    'mode' => 'keypad'
));
conference($response->value);
?>

Let’s tell them if their conference ID was accepted and notify them they’re entering the room.

<?php
$response = ask('Enter your conference ID. Press the pound key when finished.', array(
    'choices' => '[3-10 DIGITS]',
    'terminator' => '#',
    'mode' => 'keypad'
));
say('Conference ID ' . $response->value . ' accepted. You will now be placed into the conference. Please announce yourself.');
conference($response->value);
?>

Hmm. That conference id is being read as a number (one thousand two hundred thirty four) instead of as digits (one two three four). A little ssml magic will fix that.

<?php
$response = ask('Enter your conference ID. Press the pound key when finished.', array(
    'choices' => '[3-10 DIGITS]',
    'terminator' => '#',
    'mode' => 'keypad'
));
say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Please announce yourself.</speak>');
conference($response->value);
?>

Often I hit the wrong conference id and need to hang up and try again. For our conference line, how about we let someone exit the room and pick another one.

We’ll add a loop that loops as long as the call is active. Once someone exits, the loop starts over and they’ll be prompted for their conference id again. We’ll also add a terminator to the conference so someone can exit and let them know that option is available.

<?php
answer();
while ($currentCall->isActive()) {
	$response = ask('Enter your conference ID. Press the pound key when finished.', array(
	    'choices' => '[3-10 DIGITS]',
	    'terminator' => '#',
	    'mode' => 'keypad'
	));
	say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Press pound to exit without disconnecting. Please announce yourself.</speak>');
	conference($response->value, array('terminator' => '#'));
}
?>

What if someone doesn’t enter a conference id? Or enters too few or too many numbers? Let’s check the return of the ask function to see if the ask succeeded, failed, or timed out. If it’s a timeout or failure, play a message and the loop starts again, asking for the conference id again.

<?php
answer();
while ($currentCall->isActive()) {
	$response = ask('Enter your conference ID. Press the pound key when finished.', array(
	    'choices' => '[3-10 DIGITS]',
	    'terminator' => '#',
	    'mode' => 'keypad'
	));
	switch($response->name) {
    case 'choice':
      say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Press pound to exit without disconnecting. Please announce yourself.</speak>');
      conference($response->value, array('terminator' => '#'));
      // Pause a moment before asking for another conference.
      sleep(1);
      break;
    case 'badChoice':
      say('Sorry, that is not a valid conference ID.', array('voice' => $voice));
      break;
    case 'silenceTimeout':
    case 'timeout':
      say('Sorry, I didn\'t hear anything.', array('voice' => $voice));
      break;
  }
}
?>

Now that we are handling a timeout, the default timeout seems way too long for this type of application. If the user doesn’t enter a conference ID in 8 seconds, prompt again.

<?php
answer();
while ($currentCall->isActive()) {
	$response = ask('Enter your conference ID. Press the pound key when finished.', array(
	    'choices' => '[3-10 DIGITS]',
	    'terminator' => '#',
	    'mode' => 'keypad',
	    'timeout' => 8
	));
	switch($response->name) {
    case 'choice':
      say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Press pound to exit without disconnecting. Please announce yourself.</speak>');
      conference($response->value, array('terminator' => '#'));
      // Pause a moment before asking for another conference.
      sleep(1);
      break;
    case 'badChoice':
      say('Sorry, that is not a valid conference ID.', array('voice' => $voice));
      break;
    case 'silenceTimeout':
    case 'timeout':
      say('Sorry, I didn\'t hear anything.', array('voice' => $voice));
      break;
  }
}
?>

What if we want to restrict the conference IDs that someone can use? Maybe create a conference application that uses reservations and creates rooms for people. We could fetch a list of currently-valid conference IDs from a database. In this sample, I’m just going to hard-code those in an array.

<?php
$pins = array();
$pins['1337'] = '';
$pins['1234'] = '';
$pins['2600'] = '';
answer();
while ($currentCall->isActive()) {
	$response = ask('Enter your conference ID. Press the pound key when finished.', array(
	    'choices' => '[3-10 DIGITS]',
	    'terminator' => '#',
	    'mode' => 'keypad',
	    'timeout' => 8
	));
	switch($response->name) {
    case 'choice':
	    if (!array_key_exists($response->value, $pins)) {
	      say('Sorry, that is not a valid conference ID.');
	      break;
	    }
      say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Press pound to exit without disconnecting. Please announce yourself.</speak>');
      conference($response->value, array('terminator' => '#'));
      // Pause a moment before asking for another conference.
      sleep(1);
      break;
    case 'badChoice':
      say('Sorry, that is not a valid conference ID.', array('voice' => $voice));
      break;
    case 'silenceTimeout':
    case 'timeout':
      say('Sorry, I didn\'t hear anything.', array('voice' => $voice));
      break;
  }
}
?>

Now for a fun feature. Let’s let conference ID owners — the room administrator — get a text message any time someone joins their conference room. Never miss a conference call again. And for kicks, send a text message when they leave, too.

<?php
// An array of conference IDs and phone numbers to alert.
// If a conference ID is used that has a phone number attached,
// when someone joins or leaves that conference, the attached phone
// number will get an SMS alerting them.
$pins = array();
$pins['1337'] = '14075551212';
$pins['1234'] = '19255556789';
$pins['2600'] = '';
answer();

while ($currentCall->isActive()) {
  $response = ask('Enter your conference ID. Press the pound key when finished.', array(
      'choices' => '[3-10 DIGITS]',
      'terminator' => '#',
      'mode' => 'keypad',
      'timeout' => 8
  ));
  switch($response->name) {
    case 'choice':
      if (!array_key_exists($response->value, $pins)) {
        say('Sorry, that is not a valid conference ID.');
        break;
      }
      if (array_key_exists($response->value, $pins) && !empty($pins[$response->value])) {
        // Send an alert that someone has entered the conference
        message($currentCall->callerID . ' has entered conference ' . $response->value, array('to' => $pins[$response->value], 'network' => 'SMS'));
      }
      say('<speak>Conference ID <say-as interpret-as="vxml:digits">' . $response->value . '</say-as> accepted. You will now be placed into the conference. Press pound to exit without disconnecting. Please announce yourself.</speak>');
      conference($response->value, array('terminator' => '#'));
      if (array_key_exists($response->value, $pins) && !empty($pins[$response->value])) {
        // Send an alert that someone has left the conference
        message($currentCall->callerID . ' has left conference ' . $response->value, array('to' => $pins[$response->value], 'network' => 'SMS'));
      }
      // Pause a moment before asking for another conference.
      sleep(1);
      break;
    case 'badChoice':
      say('Sorry, that is not a valid conference ID.', array('voice' => $voice));
      break;
    case 'silenceTimeout':
    case 'timeout':
      say('Sorry, I didn\'t hear anything.', array('voice' => $voice));
      break;
  }
}
?>

And there’s a full-featured conference calling application in about 50 lines of code. We started with a basic one-liner and slowly added features to build a conference calling service that rivals the professional conference applications. The full code is available from the Tropo Samples repository on Github. The download on Github has some additional configuration, like allowing you to set a voice for all the prompts and turn on and off the feature that restricts this to known conference IDs.

How robust is the code? This exact application is what we use every day as our conference calling line. Calls with customers, sales prospects, and each other all happen over a conference line backed by the code in this tutorial.

Tropo Sponsors the Summer of Smart

Friday, June 24th, 2011

Tropo is thrilled to be sponsoring the Summer of Smart program in the City of San Francisco.

Summer of Smart

“Sumer of Smart” is a three month long series of events and discussions centered around urban innovation – it will bring together people from many different disciplines to work on strategies and applications to benefit those that live in, work in and visit the City of San Francisco.

This series of events began recently with a forum bringing together Mayoral candidates in San Francisco at the Pier 38 offices of Automattic, followed by CityCamp San Francisco. We were delighted to be a part of these events, and are just as excited to help support the Summer of Smart.

Our primary interest is – not surprisingly – hacking and app building! Our platforms and APIs are ideal for building things that can make urban environments easier to navigate, to live in and to visit.

A great example of the awesome apps that you can build with Tropo can be seen by looking at the results of the recently concluded Applications for Good competition – one of the winners (SNAPFresh) was built using the Tropo platform.

This innovative and very useful application lets anyone quickly and easily find the location of retailers that accept Supplemental Nutrition Assistace Program (SNAP) cards in the Bay Area by sending a text message.

It is these kinds of innovative applications we hope to foster by sponsoring the Summer of Smart.

If you are interested in attending one of te Summer of Smart events, you can head on over to their site and find one that matches your interest. You can also submit ideas for Summer of Smart on the website, or by tweeting with the hashtag #SoSIdeas.

We can’t wait to see all of the great ideas and new applications that come out of this summer-log series of events!

Realtime Conferencing Dashboard with Tropo and Chloe

Wednesday, June 22nd, 2011

In yet another installment on this blog demonstrating how to build realtime applications with Tropo, I walk you through the process of creating a conferencing dashboard with Tropo and the Chloe realtime web server from Mashion.

Chloe is a great open source project that works extremely well with the Tropo platform. With Chloe and some modest Tropo and jQuery code, you can build a sophisticated and powerful conferencing dashboard.

You can get executables for Chloe by visting the Chloe GitHub repo, and you may also download the source and build on your local machine as well.

The sample code that I demonstrate in this screencast is also available on GitHub.

This example demonstrates yet again how ideal Tropo is for building powerful realtime communication applications. Chloe is easy to work with, powerful and open source, making it an excellent compliment to the apps you can build with the Tropo platform.

Check out the Chloe project and stay tuned to this blog for more posts in the future about building realtime apps with Tropo.

php|tek hackers and winners

Monday, June 20th, 2011

room keys at tek

The hotel room keys from php|tek

At php|tek last month, the Tropo-sponsored hackathon and contest attracted a dozen development projects, nearly 100 people, and lots of hacking with Tropo and other apps.

A dozen people even stayed up all night long trying to complete their projects before the 9am deadline. In the end, five teams managed to finish their applications and submit them before judging started.

Entries were judged by SourceForge’s Elizabeth Naramore and Tropo’s Adam Kalsey on how well they used Tropo’s features, the quality of the end-user experience, and the viability of the project – are people likely to use it?

First place and an iPad 2 went to TropoNote by Savva Korolev and Neil Mansilla. TropoNote is a note-taking application that allows you to take quick notes by sending in a text message or IM or leave voice notes by making a phone call. Notes can be viewed on the site or in your Evernote account. Yes, they included Evernote integration in their app.

Second Place was won by Jeffrey and Greg Wilson’s cALLOWED, a voice-based phone number verification and captcha library for PHP. Web developers can include cALLOWED in their forms to validate a phone number. The Wilsons took home a Parrot AR.Drone Quadricopter.

Third place went to Call Couch by Benjamin Young. Use IM or SMS to look up documents in CouchDB or send the formatted contents of a Couch document to the phone number of your choice. Benjamin won a Kindle for his prize.

Honorable mention goes to the other two developers who managed to deliver a working, testable application after a night of hacking.

Brooks Boyd built a group die rolling application for SMS. Send a text message to roll any size die and all your RPG buddies will get a text letting them know what you rolled.

William Bond mashed up Twitter, a little oAuth magic, and Tropo to read your Twitter direct messages to you over the phone.

Thanks to these five teams as well as all the other people who worked on Tropo apps or pitched in with the open source projects that were represented.

We look forward to doing this again next year.

Tropo Sponsors CityCamp San Francisco

Friday, June 17th, 2011

Tropo is proud to be a gold sponsor of CityCamp San Francisco, taking place on Saturday, June 18th.

CityCamp San Francisco

CityCamps are “unconference” events focused on innovation for municipal governments and community organizations. This particular CityCamp event is the second in a series of events taking place in San Francisco this weekend focused on open government.

The first, a debate among mayoral candidates at the Pier 38 offices of Automattic, sponsored by GovFresh, focused on the use of open data to encourage civic engagement. CityCamp San Francisco follows two days later and bookends this important discussion nicely with a day long series of talks and presentations by those in the Gov 2.0 community.

We are delighted to be taking part in this important conversation among San Franciscans as they gather to discuss ideas on how they can make their city better.

Tropo is a platform that can be used to build innovative applications that connect people to their communities and to make delivery of public services easier and more efficient.

In the recent Applications for Good competition, team SnapFresh built a Tropo-based application to help those on public assistance in the Bay Area to find locations in their communities that sell fresh produce and other nutritious foods.

It is innovative uses of communication technologies like this that we hope to encourage through our sponsrship of events like CityCamp.

We’re looking forward to a great event and we hope to see you there.

Testing production applications against new builds

Tuesday, June 7th, 2011

Tropo maintains two clusters for your applications to run on. Our free developer applications run on one cluster of servers and paid production applications run on a separate cluster. This affects you and your applications in a few ways, and opens up some possibilities for development and testing.

I’m going to spend a few blog posts talking about how to use our development and production servers effectively. First up, I’ll talk about you can use the two types of servers to ensure bug-free upgrades.

Every few weeks we complete a development cycle and determine if the work completed is ready to be published into our network. We take into account our testing and QA, what sort of issues are found in the existing builds on the network, and the number and significance of any bug fixes in this build.

When we determine that we have a build we’d like to put on the network, we first push this to the servers that run free developer applications. We do this for a few reasons. First, it means that the build is exercised to find any bugs missed during QA and that these bugs are found before they can impact production applications.

Second, it allows you as a developer to test your production code against new Tropo software before your production apps start running on the new software. Tropo software builds are pushed to production after they’ve run for at least a week on our developer clusters. For some builds, for instance, those with significant changes like an upgrade of Ruby or PHP, we’ll wait even longer to move them to production. This week, we’re planning on promoting a production build that has been running our developer clusters since April 18th. It was a big change, and we wanted to make sure we had it right.

You can find out about new developer builds by subscribing to the Tropo changelog at http://changes.tropo.com/ or following @TropoChanges on twitter.

To test your production application against the latest developer build, simply create a second application and leave it in development mode. Put a copy of your code in this second application and run your tests. This second application will be running against the latest Tropo build, allowing you to validate your code against it.

While we take great care to ensure that our upgrades do not break customer applications, this extra validation step can help make sure that if a bug does slip through, we can catch it before it affects your application’s users.

In future posts, I’ll talk about A/B testing, automated deployment, and how we route calls and messages within our network.

RHoK 3 Seattle Roundup

Tuesday, June 7th, 2011

What an amazing weekend the Tropo team had across the country this weekend, with Tropo representing at simultaneous events in Seattle, Philadelphia, New York City & Raleigh.  In Seattle, Tropo teamed up with Geeks Without Bounds to be the U.S. Main Stage event for Random Hacks of Kindness.  We gathered folks from NASA, Microsoft, Crisis Commons, Code for America and brought together geeks like Chris Pirillo (founder of Gnomedex), Chris Metcalf (Socrata), Mike Laine (Liftport Space Elevator) and Ed Jezierski (CTO of Instedd).

It was an unforgettable weekend, kicked off Friday night with a reception featuring awesome DJ’s Turbo & Maxx, aerial acrobatics by the magnificent Zita the Aerialist and lightning talks by VIPs from the representing organizations.  The folks from SecondMuse posted some raw video of the lightning talks.  At about 28 minutes into this video, as I was about to begin my talk, I was encouraged to throw the words I had prepared out the door and instead played an impromptu chorus of Billy Joel’s Pianoman.  Never in my life could I have imagined this particular course of events:

 

RHOK#3 Seattle Reception from Gerty on Vimeo.

 

 

But it was Saturday and Sunday when we rolled up our sleeves and got to work. Some of the hacks that were worked on that featured Tropo:

SAARAA : Situation Awareness And Rapid Assessment App, collecting data from various places via phone apps, voice, text, etc and collecting that information into a crisis map.

Open211 : A Directory of city social services. Search is live. Portland, Oakland, and San Francisco.

Tethered Towers : weather data and communications devices attached to ballons to assist when traditional communications are down and local data is needed (toxic plume detection, gun fire detection etc).

MoveFood: Matching restaurants & people with excess food to individuals who are hungry.

Sincere thanks to everyone who came and hacked. I think we’re all quite a bit blown away by the incredible synergy that was created this weekend. Extra thanks to our excellent venue hosts at Microsoft, folks from SecondMuse and especially Willow Brugh from Geeks without Bounds, who wrangled the entire weekend together with brute force and determination to make a difference.

More pics from RHok3 events all over the world this weekend are available on the Flickr Stream

Tropo Goes To “Raleighwood”

Thursday, June 2nd, 2011

Tropo will spend the better part of two weeks in the Raleigh, NC area for a series of events, and will be helping hackers and developers of all stripes there to build cutting edge communication apps.

CityCamp Raleigh

On Thursday, June 2nd, we’ll be at the Raleigh-area Ruby Brigade Hack Nite. Look for John Dyer of Tropo if you want to talk about building awesome phone and SMS apps with Tropo using Ruby on our scripting platform, or our Tropo and SMSified Ruby Gems.

Over the weekend, from June 3rd through the 5th, we’ll be at CityCamp Raleigh – an awesome event we are sponsoring that is aimed at bringing together passionate, talented people to make government work better through the innovative use of technology. Be on the lookout for the aforementioned Dyer and Adam Kalsey of Tropo at this awesome event.

On June 8th, we’ll be meeting with PHP and MySQL developers at NC State to talk about how to build Tropo apps with PHP. Adam Kalsey will present on how PHP developers can use our scripting platform, or one of our PHP libraries to build powerful multichannel communication apps.

We’re looking forward to working with all of the great developers in the area to build some cool apps at these (and other) events.

Hope to see you there!