Posts Tagged ‘PHP’

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.

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.

Hack and win with Tropo at php|tek

Friday, May 13th, 2011

It’s ironic that most developer conferences are nothing but speakers. It’s like developers spend all year avoiding meetings so they can come to one event and do nothing but sit in meetings for a few days.

I don’t know about you, but I like my developer conferences to include a little developing.

At php|tek in Chicago May 24-27, Tropo is hosting a developer contest and a hackathon on Thursday night. We want to help you take all the ideas you’re learning at the conference and put them into practice building something useful. We’re starting the hackathon right after all the sessions are over, so you won’t even need to miss your favorite speaker.

In addition to Tropo, a large number of other projects will be at the hackathon to help you get started with their stuff. CouchDB, Frapi, Gowalla, JoindIn, Node.js, Phergie, PEAR, PHP Core QA, Spaz, web2project, Windows Azure, and Zend Framework will all be represented, in many cases by the project creators and leads. You don’t need to hack on one of these projects, of course, but we’ll all be there to help and answer questions if you want to.

“But I was going to go grab dinner and a drink!” you might say. Well, hey, we’ll have food and drink there, too. “I was going to hang out with my friends!” They’re all going to be there. “I need to go shoe shopping.” Uhhh, you’re on your own there. See you when you get back.

In addition to the Thursday hack event, Tropo’s putting on a contest. Build an application using Tropo and PHP, and win fabulous prizes. You can work on it at the hackathon or on your own time.

The developer contest runs all through the conference. Heck, start today if you want. Tropo’s communications APIs are free for development use and have native PHP support, so there’s no reason not to enter. Entries are due Friday at 9am and a panel of your brilliant peers will be judging you, or at least your application, to pick a winner to announce at the closing keynote.

The Official Rules for this contest can be found on the Tropo site. The highlights are…

  • Contest open to residents of the 50 United States and DC 13 or older
  • Eligible entries must use Tropo and PHP
  • Contest runs from May 12, 2011 12:00am Central time to May 27, 2011 9am Central time
  • Prizes are an Apple iPad for first place, second place gets a Parrot.AR Drone quadricopter, and third place wins an Amazon Kindle.
  • Entries will be judged according to the Extent of Tropo Features Utilized, End User Experience, and Perceived Commercial Viability
  • To enter, complete the entry form at http://bit.ly/TropoTek11

In case that’s not enough Tropo-powered goodness for you, I’ll be giving two different talks at php|tek. Wednesday at 3pm, I’ll be showing how you can use Drupal as an Application Development Platform. The next day, Thursday at 4pm, come hear why you should be adding Voice, IM, and SMS to your web applications and how to do it with Tropo, Phono, and a variety of open source tools and open standards.

We look forward to seeing you at tek! Bring your questions, your code, and your laptop. We’ll take care of everything else.

Hacking a Better World

Thursday, May 5th, 2011

At Tropo, we like to think that hackers can change the world.

It’s one of the reasons we like to be involved in and support events that let developers improve cities, and make their communities better places to live.

orchestra.io

That’s why we were excited to hear that the good folks over at Orchestra will be holding a “HackForGood” night at their San Francisco offices on Monday May 9th.

We’ll be participating in this event, and are looking forward to helping people build awesome things for their communities.

Orchestra is a PHP deployment platform that provides powerful scaling and management for your PHP applications. Their platform is a great fit for Tropo applications, and we blogged recently about how simple it is to deploy Tropo apps to the Orchestra platform.

If your in San Francisco on May 9th, join us at the Orchestra offices for a fun night of hacking that has the potential to make a real difference.

Hope to see you there.

Join us at DrupalCamp Nashville

Thursday, April 28th, 2011

We had so much fun with the PHP community last week in Nashville that we’re returning this weekend for DrupalCamp Nashville.

We’re supporting the local Drupal community as a Gold sponsor, and Adam Kalsey will be there all day Saturday with Tropo shirts and goodies and showing people how to integrate voice and SMS into their Drupal applications.

In the afternoon, come hear Adam’s talk on using Drupal for all your web app development needs.

Drupal – it’s not just for content!

Empire Avenue Stock Quotes by SMS

Tuesday, April 26th, 2011

Have you heard of EmpireAvenue? According to their website, “Empire Avenue is the Social Media Exchange, where you can buy and sell shares in any social media profile, meet new people, unlock Achievement badges, and earn boatloads of virtual cash by being active and social online! Buy shares in your friends, your followers, people with similar interests, brands you love, celebrities – anyone! All using a virtual currency and all for free!”

Cas Hoefman, a long time telephony geek and friend of Tropo, built an SMS hook into their API!

If you want to see a working sample just send a text message with DISRUPTIVE to (818) 900-2731 to get back our latest stock price or replace DISRUPTIVE with your own Empire Avenue Ticker Symbol to get your own latest stock price!  You can also scan the QR code on the left and we’ll do it for you.

Using Tropo, you can add SMS to virtually API to further extend services to meet your needs.  For more details on Cas’ application including the source code, please visit his blog post!

Deploying Tropo Apps with Orchestra.io

Friday, April 22nd, 2011

On a visit to Nashville, Tennessee, for the PHP Community Conference (Tropo is one of the sponsors) I got to hear a talk from Helgi Þorbjörnsson on front-end caching techniques.

During his talk Helgi mentioned a new Git-based deployment service for PHP applications – Orchestra.

Orchestra is very similar to other Git-based deployment service for different langages – Heroku for Ruby, and Nodester for Node.js – but it’s meant to support deployment of PHP-based applications.

If you’re like me, and you missed the chance to take part in the Codeita beta, you’re anxious to give a Git-based deployment service for PHP a try. When I checked out Orchestra, it looked incredibly easy to use, and a snap to get started with.

It’s also an excellent match for Tropo applications written with our PHP class library for WebAPI.

How easy is it to use Orchestra to deploy a PHP-based Tropo app?

I was able to write, deploy and test an app before Helgi had finished his presentation at the PHP Community Conference (about 20 minutes total with conference-grade wifi). I was even able to hear the end of Helgi’s talk.

Here is how I did it.

Building a Tropo WebAPI App

I built a very simply Tropo application using the PHP class library WebAPI.

My sample application is meant to answer an incoming call, ask the caller what their favorite programming language is (along with some choices), and then say something snarky based on their response.

Building a speech recognition app like this with Tropo is very easy. I also made use of the awesome Limonade PHP framework for my app.

All of the code for this app is made available on GitHub, which is also part of the process for deploying apps to Orchestra.

Setting up and Deploying to Orchestra

Orchestra settings

Go to the Orchestra site and create a new account. Take a spin through the knowledge base if you want more specifics on how everything works – you have two deployment options, a free deployment or an elastic deployment.

For the purposes of this post, I’ll use a free deployment.

You deploy your application to Orchestra by connecting a repo on GitHub with your Orchestra account – Simply set up a GitHub repo for your app, just as you would for a normal project. You’ll then use information about this repo to set things up in Orchestra.

When you tell Orchestra where your GitHub repo is, it will deploy your app and give you a public URL that you can use to access it.

Setting up a Tropo Application

Now that our application is deployed to Orchestra, we need to set up a phone number to use it in Tropo. Like all of the steps described above, this one is simple.

Log into your Tropo account and create a new application – when prompted select WebAPI. The URL that powers your application is the public URL provided by Orchestra when you deploy your application.

Since we’re using Limonade, we need to add a query string parameter for our starting route.

In our application, our starting route looks like this:

dispatch_post('start', 'tropoStart');
function tropoStart() {
 ...
}

So to access this route from Tropo, we would set up our app URL like this.


http://my-app-name.orchestra.io/index.php?uri=start

When you do this, you’ll be able to call the application and hear it work. Here is a quick screencast demonstrating how the app works.

One of the things I really like about Orchestra is that it uses a standard GitHub repo for deployment. Similar services for other languages often require you to set up a special stand alone repo for deployment, and for me this just always feels like an extra step I have to go through to deploy my app.

I love that I can push changes to GitHub and they are deployed by Orchestra. Quick and easy!

Orchestra has a number of add ons planned (i.e., for CouchDB and MongoDB) so it’s only going to get more awesome.

So if you want a fast, easy way to build powerful multi-channel communication apps in PHP, Tropo and Orchestra make a powerful combination.