How to play music over phone calls with Twilio Voice and JavaScript

August 20, 2015
Written by
Sam Agnew
Twilion

banner

When handling phone calls with TwiML, you have many options for controlling the caller’s experience. You can  something in a robot voice,  other numbers into the call and even  the call. My personal favorite is the ability to play audio files over the phone using the  TwiML verb. You can even create your own version of Dial-A-Song, a hotline run by the band They Might Be Giants that allows you to listen to their music if you call the number (844) 387-6962.

Today I’m going to show you how to make and receive phone calls using the Node.js Twilio library. We will also be using some ES6 features to “spice things up a notch.” What better way to show what we can do with Twilio voice than to allow the callers to rock out over the phone?

Zelda3RockOut.gif

Here is our code in full on GitHub  if you want to skip straight to having a working app.

Gearing up

We are going to need to grab some gear and tune up first. For starters, you’ll need to have have Node.js and NPM installed. You will also need to create a Twilio account and purchase a phone number with Voice capabilities.

Now let’s initialize a new app. Open your terminal, navigate to the directory you want to start this project in and run:

npm init

This will generate a package.json file that will contain all of the information about our project. Feel free to breeze through the prompts if you are not interested in customizing the default options.

After you have that taken care of we can install our dependencies.

We will need the Twilio Node module so let’s grab that:

npm install twilio --save

When our phone number receives a call, Twilio will make an HTTP request to the URL that we provide. We will have to create a web app to handle these incoming calls. Let’s use the Express web framework to do this:

npm install express --save

We will also need to install Babel in order to run our ES6 code. Babel is a compiler for JavaScript that can turn your ES6 code into regular ES5 JavaScript that will run everywhere.

Installing Babel globally will allow you to use the babel-node command line tool which can directly run your ES6 code. You may need to use sudo to run this command:

npm install --global babel

Now that we have all of our dependencies installed we still need one important thing: a song to play over the phone. I was having trouble figuring out which tune would be appropriate until I realized there exists a song that goes with everything.

For those of you who don’t know, this is the infamous Guile’s Theme from Street Fighter 2. Luckily for us there exists even better versions of this tune provided by the wonderfully talented community of musicians at OverClocked ReMix. A band called Shinray did a metal remix of Guile’s Theme that manages to surpass the original in terms of epicness. This is freely hosted online making it a perfect candidate for our phone call’s soundtrack.

sonicboom.gif

Try calling (347) 826-3536 to hear “Guile’s Theme Goes with Metal” over the phone for a sneak peek at what we are building.

Generating some TwiML

Now we are ready to build our application. The first step is to create a web app that will respond to incoming HTTP requests with TwiML – a set of XML tags that will tell Twilio what to do when you receive an incoming call. This web app will generate TwiML instructions to play the mp3 file of the Guile’s Theme remix that we are using.

Let’s start working on our Express app to take care of this. You may not be familiar with some of the new features of ES6 so let’s walk through the code that our app will contain step by step. Fire up your text editor and create a file called “index.js” where we will write our app.

First we need to import the modules we will be using. You may be used to something like

var express = require('express');

but we can use new ES6 import statements instead:

import express from 'express';
import twilio from 'twilio';

Next we need to create an app object and add a route to it that will accept HTTP requests from Twilio.

let app = express();

app.post('/voice', (req, res) => {});

Notice that we used the new arrow syntax in the anonymous function that we passed to app.post() rather than using the traditional function keyword. Arrow functions lexically bind the outside scope’s this variable to the function that you’re writing.

Now let’s fill out the function that we are giving to app.post:

app.post('/voice', (req, res) => {

  // Set the url of the song we are going to play
  let songUrl = 'http://ocrmirror.org/files/music/remixes/Street_Fighter_2_Guile%27s_Theme_Goes_with_Metal_OC_ReMix.mp3'

  // Generate a TwiML response
  let twiml = new twilio.TwimlResponse();

  // Play Guile's theme over the phone.
  twiml.play(songUrl);

  // Set the response type as XML.
  res.header('Content-Type', 'text/xml');

  // Send the TwiML as the response.
  res.send(twiml.toString());
});

Here we are using the let keyword to declare our variables. It allows us to use block scoping instead of JavaScript’s traditional functional scoping with the var keyword. This allows us to avoid adding variables to the function scope that are only relevant to a particular block.

All we have left to do is to declare the port our server will listen on:

// Make our Express server listen on port 3000.
app.listen(3000, () => console.log('Listening at http://localhost:3000'));

We are using another anonymous arrow function, but this time it will be a one liner withno arguments. It may look strange at first, but this syntax allows us to keep things concise.

Here is the entire code for our Express server in case you missed anything:

import express from 'express';
import twilio from 'twilio';

let app = express();

app.post('/voice', (req, res) => {

  // Set the url of the song we are going to play
  let songUrl = 'http://ocrmirror.org/files/music/remixes/Street_Fighter_2_Guile%27s_Theme_Goes_with_Metal_OC_ReMix.mp3'

  // Generate a TwiML response
  let twiml = new twilio.TwimlResponse();

  // Play Guile's theme over the phone.
  twiml.play(songUrl);

  // Set the response type as XML.
  res.header('Content-Type', 'text/xml');

  // Send the TwiML as the response.
  res.send(twiml.toString());

});

// Make our Express server listen on port 3000.
app.listen(3000, () => console.log('Listening at http://localhost:3000'));

Now let’s run our server:

babel-node index.js

Open up a new terminal window and try hitting it with curl to make sure everything is working and we receive XML as a response:

curl -X POST http://localhost:3000/voice

Our response should look like this:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
    <Play><a href="http://ocrmirror.org/files/music/remixes/Street_Fighter_2_Guile%27s_Theme_Goes_with_Metal_OC_ReMix.mp3">http://ocrmirror.org/files/music/remixes/Street_Fighter_2_Guile's_Theme_Goes_with_Metal_OC_ReMix.mp3</a></Play>
</Response>

In order for Twilio to see our application and for us to be able to receive phone calls, we need to expose our server to the Internet. We can do this using ngrok. If you want to learn how to set up ngrok, you can follow my buddy Kevin’s tutorial.

Once you have that taken care of, have ngrok listen on port 3000:

ngrok http 3000

You should see a screen that looks like this with a generated link that we can visit to access our Express app.

We need to add this URL to our Twilio phone number in the account phone numbers dashboard so Twilio knows to send us an HTTP request when a call is received.

phonenumberpage

It’s time to win round one of our battle. Whip out your phone and give your Twilio number a dial to have quite possibly the most epic phone call of your life.

Initiating phone calls with NodeJS

Being able to call a phone number to hear a rockin’ version of Guile’s theme is a ton of fun. But we can also start the call ourselves with a little bit of code. This involves using the Twilio REST API.

We are going to write another quick Node script that will send a phone call to a number of your choice using the TwiML we generated earlier to play the same song.

Create a file called “makeCall.js” in your text editor and add this code:

import twilio from 'twilio';

// Account SID and auth token are stored in environment variables.
let twilioClient = twilio();

twilioClient.makeCall({
  to: 'the_number_you_are_calling',
  from: 'your_twilio_phone_number',
  url: 'your_ngrok_url'
});

Don’t forget to replace the variables with their appropriate values (a phone number to call for testing, your Twilio number, and the URL to the TwiML that your Express app is generating).

This is all the code we need to make phone calls, but we still need to authenticate with Twilio. Head over to your Twilio account dashboard and grab your Account SID and Auth Token. Store them in environment variables like so:

export TWILIO_ACCOUNT_SID='your_account_sid_here'
export TWILIO_AUTH_TOKEN='your_auth_token_here'

No need to add these to your code, because upon initialization of the REST client object, the Twilio Node module checks to see if these environment variables exist.

You should now be able to make a phone call by entering the following in your terminal:

babel-node makeCall.js

Now listen in amazement as you once again experience the epicness of Guile’s Theme, this time initiated by your code.

FlashKick.gif

You Win

You’ve won round 2 by implementing an app that can make and receive phone calls using the Twilio Node.js module, and even got it running with newer ES6 features. You are now ready to change your app to play different music files or utilize some of the other TwiML verbs that you haven’t messed around with yet. I am excited for you to move on to the next round, and look forward to seeing what you build with Twilio Voice.

Screen Shot 2015-08-19 at 2.28.11 AM.png

Feel free to reach out if you have any more questions or want to show off your hacks.

Email: sagnew@twilio.com
Twitter: @Sagnewshreds
Github: Sagnew
Twitch (streaming live code): Sagnewshreds