Build a Dial-in Podcast Service with Programmable Voice, TwiML Bins, and Functions

June 18, 2020
Written by
Andrew Milner
Contributor
Opinions expressed by Twilio contributors are their own
Reviewed by
Paul Kamp
Twilion

Dial-in Podcast Hero

I read a great article recently about accessibility. It stressed that it’s important to cater for those who either don’t have a computer or who, quite frankly, find computers and the internet too daunting. And then I thought about the current trend to move everything online, from shopping to social events; and, more recently, even church services!

Imagine a world in which all your neighbors for miles around get together for church services several times a week, but you can’t take part. They don’t deliberately exclude you, but for whatever reason, you can’t join in.

It’s unthinkable, isn’t it?

However, in these days of social distancing and lockdown and online everything, that’s exactly the predicament we face. Sadly, this is a situation where those who are isolated – due to frailty, illness, poverty, or other reasons – have always found themselves.

Fortunately, it doesn’t have to be that way, thanks to the trusty telephone – using our common bond, we can build a dial-in number which delivers a sermon or podcast to our isolated community members. In this post, I’ll show you how to do this using Twilio Programmable Voice and a range of other Twilio products.

What you need to start

There are many communications platforms which enable you to make web content such as a podcast available over the phone. I opted for Twilio.

If you haven’t done so yet, sign up for a free Twilio account. If you use this link, when you sign up, we’ll both receive $10 in Twilio credit when you upgrade.

Other than that, you will at some point need a telephone too – any old phone will do, ideally from post-1900!

No coding skills are required. You’ll just need to cut and paste the sample code; I’ll show you how to adapt it to your needs. And you don’t need any fancy gadgets or software – Twilio will take care of all that for you. Alternatively, if you would find a visual interface more appealing, follow this link to build a Podcast IVR menu with Twilio Studio.

Your first Twilio phone number

When you sign up to Twilio, it automatically gets you started with some free credit and a project called 'My first Twilio project'.

Incidentally, it's easy to change your project's title to something more meaningful, if you wish. Just click on the ‘cog wheel’ icon, in the top right corner, then ‘Settings’ and change the wording in the 'Project Name' box. (For your protection, it may ask you to enter your password first.)

New Twilio project screen

More importantly, the sign-up process doesn't automatically allocate you a phone number. If you haven’t yet purchased one, let’s do that now.

Click the red “Get a Trial Number” button.

If you don’t see the button, not to worry; it’s a good opportunity to explore the menu!

Click on the three “dots” in the left column to bring up the menu, then select “Programmable Voice”. On the Programmable Voice Dashboard, select ‘Numbers’ which should be the fourth item down. On the Phone Numbers screen, go ahead and click the red “Get a Number” button.

Choose your first number

A pop-up entitled ‘Your first Twilio Phone Number’ will appear, offering you a US number. If you or your clients are US-based, feel free to ‘Choose this Number’; if not (or if you’d prefer to choose a different number), click or tap ‘Search for a different number’.

The Buy a Number screen is very straight-forward. Just select your country and – if you want a local number – the area code, which you should enter in the  “NUMBER”  box (making sure that the “MATCH TO” drop-down says ‘First part of number’). By the way, if area codes in your country begin with a zero, you don’t need to include the zero in your search.

When you click ‘Search’, a list of available numbers will appear. Choose the one you like the look of (or click ‘Refresh results’ to try again) and click ‘Buy’ in the right-hand column. Review your selection on the following screen, then click ‘Next’ and confirm your purchase.

Rest assured, you’re not signing up for a long contract. There’s nothing at all to pay until you ‘upgrade’ from trial mode, and, thereafter, you can release the number and cease paying the monthly fee at any point. You can review the monthly recurring charge (MRC) and usage costs for your Twilio number here.

Wonderful!  We’re all set – let’s get building!

Your first Twilio Asset

So you’ve made a recording, and you want to make it available to anyone who dials your Twilio number. For me, this recording was the Sunday sermon in my local church, but it could just as easily be an mp3 of your daughter singing happy birthday to her gran.

You can skip this step if you’ve already uploaded your recording to your own website or to any publicly accessible site in that mysterious cloud that everybody’s talking about!

If you haven’t, I’d recommend you upload it to Twilio’s Assets.

To upload your file, visit the Assets console here and hit the ‘Add an Asset’ button. Locate the file containing your recording and upload it, choosing not to make the file private on the ‘Confirm Asset Upload’ screen.

Copying the accessible Assets URL from Twilio

To listen to your recording and make sure it has uploaded correctly, simply open a new browser window (or tab) and paste its URL into the address bar. You can easily copy its ‘path’ or URL using the ‘Copy to Clipboard’ icon to the right of the uploaded file, as illustrated above.

Save that URL – we’ll be using it in the next steps.

Consider your options

Let’s look at how we’re going to get the Twilio service to play the recording for us.

We’ll start with the simplest option, and deliver a single podcast by means of a TwiML Bin (more on that in a second).

If you’re more ambitious, the second option – using a Twilio Function – will allow you to add as many podcasts as you like.

Option 1: Keep It Simple — TwiML

By far the easiest way to make an audio recording available over your phone line is to use a simple script inside a TwiML Bin. TwiML, the Twilio Markup Language, is at the heart of all Twilio applications. It’s the set of instructions which Twilio applications need in order to respond to (or make) calls, text messages, etc.  

You can learn all about TwiML here, but for this Bin, we’ll just use the ‘Say’ and ‘Play’ instructions (or ‘verbs’) which enable you to communicate with your caller.

Create a New TwiML Bin

Surf to the TwiML Bin section of the console by clicking the 3 dots on the left sidebar. This brings up the ‘All Products and Services’ menu (illustrated below), from where you can scroll down to the RUNTIME section and select TwiML Bins. (If you can’t find it, access the Twiml Bin console here.)

Zoomed in Twilio sidebar inside the console

If this is your first TwiML Bin, you will be presented with a friendly red “Create new TwiML Bin” button. Click it and give your script a FRIENDLY NAME, such as 'Play our recording MkI'.

Here’s our 5-line script, our complete TwiML Bin:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Say>Welcome to the Saint Tim's Sermon Line. This week's sermon will start in a few seconds.</Say>
  <Play>https://www.ourwebsite.com/media/latest-message.mp3</Play>
</Response>

Copy and paste the above script into the TWIML box. (This will already contain the <?xml...> line – take care not to finish up with two.)

Twilio TwiML Bin after pasting code inside to build a podcast app

Be sure to change the <Say> section to your own greeting, and the <Play> section to the URL of your own recording.

Each TwiML ‘section’ must have an opening tag (e.g. <Say>) and a closing tag (e.g. </Say>).

All you need to do now is to click “Create”.

How this TwiML Bin works

The Bin should be self-explanatory apart from the first line, which is needed because TwiML is based on XML or ‘eXtensible Markup Language’. As mentioned above, you’ll need to reword the initial greeting to suit your particular project, and the ‘Play’ statement will need to be edited to include the url or address for your recording.

Before we continue – are you sure your recording plays? Try it out by typing or pasting its URL into the address bar of your favourite browser. If it doesn’t play or your browser can’t find it, then Twilio won’t be able to find it either.

If your recording isn’t available yet (or you can’t find it), you can temporarily replace the <Play> instruction with something like this:

<Say>Put PLAY statement here, once mp3 file is available.</Say>

Run your TwiML script:

You’ll notice there’s no ‘Run’ button. That’s because in order to run your script, you have to associate it with your Twilio phone number and then dial the number.

In effect, you’re using your telephone to log into one of Twilio’s servers, run your script and listen to the results! How cool is that?

Skip ahead to Configure your Phone Number and give it a try.

Then come right back here to learn more!

Despite their simplicity and ease of use, there’s lots more you can do with TwiML Bins. For complete flexibility, though, let’s now take a look at Twilio Functions.

Option 2: A Function to offer a choice of recordings

Another way to control your Twilio phone number is to write a small program called a function. Functions can be written in a number of popular languages, but we’re going to keep it simple and use Javascript.

Twilio functions really come into their own, when compared with TwiML scripts, in situations which require more sophisticated call or message handling, more complex ‘logic’.

A scenario where we give our callers a number of options – allowing them to choose the recording they want to hear – gives us the perfect opportunity to use this functionality. Really, what we’re building is a basic phone menu or Interactive Voice Response (IVR) system; from the callers’ perspective, though, we’re just letting them pick a path.

Let’s code a Function!

Now that you’re getting the hang of the Twilio console, open up the menu (by clicking the 3 dots on the sidebar) and skip straight to FUNCTIONS.

Click or tap the red plus sign to add a new function, or – if this is your first Twilio Function – click the friendly red “Create a Function” button. A ‘New Function’ pop-up will appear, offering you a choice of templates. By all means experiment with these later, but for now, let’s just select ‘Blank’ and click the red “Create” button.

First things first, replace the blank FUNCTION NAME, with something more meaningful, such as 'Play recording MkII', and give it a unique identifier or path on the line below. Keep it fairly short, such as 'play-menu' or 'sermon-select'. Also, under Access Control, let’s clear the check-mark or ‘tick’ alongside ‘Check for valid Twilio signature’ – more about this later.

Your screen will now look similar to the following. For illustration purposes, I’ve kept the sample code brief. In passing, note the similarity to our earlier TwiML Bin.

Twilio Function code pasted to build a choose your own podcast app

Moving on to our menu function or IVR, scroll down a little to view the code we’re going to paste into the CODE box. (Don’t be put off by the notes at the beginning: everything between /* and */ will be treated as ‘comments’ and will be ignored.)  As you will see, the key to our phone menu is the ‘Gather’ statement or verb, which is the mechanism we use to store the caller’s response.

Gather can store both keypresses and speech, but for the purposes of this tutorial, we’ll ask the caller for a single keypress, as follows: gather({numDigits: 1}). Thanks to the Gather TwiML verb, we will know which key the caller has pressed, and we can tell Twilio to play the corresponding recording.

/* Function: Welcome Menu for sermon recordings
 * Path:    /play-menu
 * Andy Milner,April 2020
 */
exports.handler = function(context, event, callback) {
let response = new Twilio.twiml.VoiceResponse();
switch (event.Digits) {

case '1':
response.say("Thank you. The latest sermon will start in a few seconds.");
response.play('https://www.ourwebsite.com/media/latest-message.mp3');
/*       The BREAK statement now exits this Switch block.     */
break;

case '2':
response.say("You have selected option 2. Last week's sermon will start in a few moments.");
response.play('https://www.ourwebsite.com/media/previous-message.mp3');
break;

case '3':
response.say("Please call the office for further information or log in to www.Saint-Tims.org.uk");
break;

default:
/* This case answers the call and gathers/stores the caller's keypress.
   This short pause means that the caller will hear 1 or 2 rings
   before the call is answered. */
response.pause({
  length: 3
  });
response.gather({numDigits: 1, timeout: 8, actionOnEmptyResult: 'true'})
.say("Welcome to the Saint Tim's Sermon Line. Please press 1 for the latest sermon, 2 for last week's sermon or 3 for further information.");
//  End of SWITCH block
}
/*  Thank callers and remind them of their options.  *
 *  Twilio runtime then reinvokes the entire routine. */
response.say("Thank you for joining us today. ... ... ... ...");
response.gather({numDigits: 1, actionOnEmptyResult: 'true', action:'/play-menu'})
.say("Please press 1 for the latest sermon, 2 for last week's sermon or 3 for further information.");
callback(null, response);
};

Be sure to blank out the default template before pasting in your new function. Cast an eye over it to make sure you haven’t inadvertently duplicated the exports.handler line, for instance.

Twilio will flag any obvious errors, by placing an [x] or an exclamation mark [!] to the left of the line number. An i or ‘information’ message usually means that you need to put a semicolon at the end of the line, as in the above screenshot. (Be wary, though;  this isn’t always the case!) Hover over or tap these small icons for clues about what’s wrong.

As before, you need to reword the greetings and prompts in the 'say' statements and to amend the paths and filenames for your mp3 files in the 'play' statements.

And finally – before clicking ”Save” – it’s important to check that the 'action' parameter of the final 'gather' statement (towards the end of your code) contains the unique path name which you assigned to your function a few moments ago; e.g.action:'/play-menu'.

Reinvoking the same function after a 'gather' statement is actually the default action. However, it does no harm to spell it out in this way, using the 'action' parameter.  Indeed, there are times when you might want to invoke a different function (i.e. to answer the incoming call with one function, but move on to a different function later in the call), so this is a useful technique to learn.

Test your Function

As with TwiML Bins, the Twilio Console doesn’t provide an option to ‘Run’ your functions because the only meaningful way to execute them is to call your Twilio number.

However, here’s a great way to give your new function a test drive, to see if it’s behaving correctly (and this is why we unticked the ‘Check for valid Twilio signature’ box earlier).

Head back to the Functions Properties page and, to the right of the box where you entered its unique pathname, click the ‘Copy’ icon.

Now open a new browser window or tab and paste your function’s path (its URL) into the address bar. What you see when you click ‘go’ or press the ‘enter’ key are the actions Twilio will take when someone calls the phone number which you assign to this function.

<Response>
  <Pause length="3"/>
  <Gather numDigits="1" timeout="8" actionOnEmptyResult="true">
    <Say>Welcome... Please press 1 for the latest sermon, etc.</Say>
  </Gather>
   . . .
</Response>

So much for the “menu”, but what will happen when the caller presses 1?  Simple, just append ?Digits=1 to the end of the URL (in the same browser window), click ‘go’ or press ‘enter’, and ‘Hey, presto!’:

<Response>
  <Say>Thank you. The latest sermon will start in a few seconds.</Say>
  <Play>https://www.ourwebsite.com/media/latest-message.mp3</Play>
  <Say>Thank you for joining us today. ... ... ...</Say>
  <Gather numDigits="1" timeout="8" actionOnEmptyResult="true" ...>
     <Say>Please press 1 for the latest sermon, etc. </Say>
  </Gather>
</Response>

It’s reassuring to see that the first part of the generated TwiML is almost identical to the script we wrote for Option 1.

If your code contains any errors or typos, a message similar to the following will be displayed: {"message":"response.SAY is not a function",…}. In this case, you just need to retype SAY in lower case, save your changes and try again.

Amend the?Digits= tag to check out each valid case, tweaking and re-saving your code here and there, if necessary. Test for invalid keypresses too, making sure that the menu greeting is repeated, so that the caller will be able to try again.

Once you’re satisfied that your function is behaving as it should, scroll on down to Configure your Phone Number and try it out for real.

Configure your Phone Number

Whether we’ve set up a couple of instructions in a simple TwiML Bin or crafted an intricate function to handle every option imaginable, your phone number won’t know what to do unless we link it to our instructions via the Twilio Console. This is called setting a Voice Handler on your phone number – but don’t worry, this is quite straightforward!

First things first, let’s navigate to the ‘phone numbers’ page.

As always, reveal the ‘All Products and Services’ menu by clicking on the 3-dot menu icon in the left sidebar, then select ‘# Phone numbers’ which will take you straight to your Active Numbers page. 

(Alternatively, you can stick to the route you followed earlier via “Programmable Voice”, then ‘Numbers’ on the next screen, then you just need to click ‘Manage Numbers’.)

There’s nothing you need to do on the Active Numbers page except to click on your Twilio number to display its configuration screen. This is where we will program your number to execute the script or function you’ve just written whenever “A Call Comes In”.

Changing the voice call webhook handler in Twilio

Scroll down to the section called “Voice & Fax”. This should already be configured to:

  • ACCEPT INCOMING:        Voice calls, and
  • CONFIGURE WITH:          Webhooks, TwiML Bins, Functions, Studio, or Proxy

Beneath the heading  A CALL COMES IN,  select the entry in the drop-down list according to the option you’ve followed: TwiML Bin for option 1, Function for option 2. Then in the larger drop-down box to the right, pick the TwiML Bin or function which you’ve just created.  All done!

Click the blue “Save” button at the bottom of the page and you’re good to go.

(Optional) Set up a Secondary Call Handler

If you’ve got your Function working and you’re feeling nostalgic for your trusty old TwiML Bin, don’t feel you have to discard it altogether!  

Instead, let’s park it on the subs bench, also known as the 'Secondary Call Handler' or ‘Fallback URL’. This is the call handler which will be invoked if the primary handler fails (perhaps it can’t find your audio recording, or you’ve mistyped something in your function). Take a glance at the screen and all will become clear:

Setting a Twilio number secondary webhook handler

So, in the drop-down called 'Primary Handler Fails', select “TwiML Bin”, followed, in the box to the right, by whatever you named your script.

Later on, you might want to replace the recording or message in your script with something more appropriate (to explain that the main recording couldn’t be found, for instance). But for now, you’ll be able to handle callers even if your Function isn’t working.

Give it a try!

It just remains to give your Twilio number a call.

For trial accounts: When you dial your Twilio phone number, before anything else happens, you’ll hear a reminder that you have a trial account. You simply need to press any key on your telephone keypad and then your TwiML script or your Function will take over.

Make sure that the correct recording is playing and/or that you’re hearing the messages and menu options you were expecting. Try pressing all the appropriate keys (testing each option in turn), plus a couple of invalid ones – just to make sure that the menu announcement is replayed and that the call isn’t unexpectedly dropped.

If necessary, amend your code, resave, and call the number again. If not, congratulations! You now have a dial-in line where you can post sermons or podcasts, and even a simple IVR that lets callers pick which one they’d like to hear.

Building a dial-in choose-your-own-sermon line

I hope you found this article helpful and got your dial-in line working.

How you use it now is entirely up to you. By all means, keep it simple and get up and running with the TwiML Bin or if that doesn't meet your needs, dive into the Functions code (and don't forget the semi-colons!). 

Of course, the world of functions and code isn't for everyone! If 'drag and drop' is more your thing, here’s a tutorial which will show you how to build your podcast selector using Twilio Studio.

As you have hopefully now discovered, none of what we’ve done is particularly difficult, it’s just a question of knowing where to start. I’m hoping that this article will be a Godsend to non-technical people, such as church admin staff and volunteers like me, who might never have dreamt that what they could achieve would be anything like this sophisticated.

Where to next? 

You now have a robust and potentially maintenance-free telephone-based podcast service. And, as you will have realized, there’s lots more you can do with Twilio phone numbers. (You could even use your Twilio number to field all your calls.)

So what’s next? Now that you have a working phone menu, you can easily add extra "cases" (one case for each valid keypress). Here are some possible enhancements:

  • A thought for the day (or prayer for the day)
  • Some general information and pointers to your website (to reduce the number of calls to admin staff)
  • Fast access to a specific section of your recording
    press 4 to skip straight to this week’s bible readings
  • How about adding a voicemail service?
    press 8 to leave a message!
  • Or, better still, the option to speak to a real person!!
    or, to talk to someone in the office, press 9!

There isn't space here to explore all the alternatives, but Twilio's collection of IVR tutorials is an excellent place to start.

If this post has whetted your appetite for all that you could achieve with Twilio Programmable Voice and you know others who might find it useful (your local church, social club, or podcaster, perhaps), please do send them a link to this blog post.

Andy is a coder and technical writer (but not too technical!), more familiar with mainframe database systems than web platforms. In the absence of 2.4 children and a loving wife, he enjoys cycling, photography, skiing, and country walks, in-between building Twilio Programmable Voice apps for charities and churches. You can see examples of what his local church is doing to keep in touch with its congregation here and here.

Find Andy online: