In Context

The next-generation communications blog from Nexmo

< Back

Making a Text-to-Speech Phone Call with Django

August 14, 2017 Published by

Amongst the incessant notifications people receive every day; a ringing phone is still much harder to ignore or overlook.

Tony Stark looking stressed

It creates a sense of urgency which makes it the perfect way to deliver critical or time sensitive messages such as two-factor authentication codes or important service notifications.

In this tutorial, we will look at how you can use Nexmo’s text-to-speech API to make outbound calls with Python and Django.

Prerequisites

You will need a Nexmo account with some available credit (the couple of free Euros you receive when creating an account should be enough) as we’re going to be renting a virtual number and making some calls. Also, an understanding of Python/Django would be beneficial but is not required. The example code is straightforward and hopefully shouldn’t be hard to follow if you have a little experience with another web-framework such as Rails, Laravel, or Express.

Your Django server will need to be reachable by the Nexmo API. If you’re running it locally, then you will need to use a tool such as ngrok to expose it to the public internet.

Nexmo applications

One final thing before we begin writing our Python/Django code we need to understand Nexmo applications. When we create a new Nexmo application not only do we use it to store configuration data such as the URL of our Nexmo call control object (NCCO), or where Nexmo should send event information; we can also use it to generate our public/private key pair.

Security is critical to us, and we do not want anyone to be able to impersonate you or your application by placing calls from your number. So to help secure our voice API we use your private key to create a JSON Web Token (JWT).

So before we begin let’s create a new Nexmo application, attach it to a virtual number and then generate and download our private key.

voice application creation screencast

Remember to keep your private key safe; I recommend using something like Vault. If you do think for any reason that someone has compromised your private key, you should stop using it immediately and generate a new public/private key pair.

Creating a basic NCCO

view on Github

The outbound voice API requires an answer_url. When someone answers our call, Nexmo will retrieve our NCCO file from this URL and execute any actions defined in it. Let’s create a Django application so we can serve up our NCCO JSON file.

We’re going to install our dependencies via pip. I’d always recommend keeping each Python project and its dependencies in their own virtual environment.

Once we have our Django project we need to create a new app, this will be where the bulk of our development happens.

After you have created your new application don’t forget to add it to your tts/settings.py, you should probably edit your ALLOWED_HOSTS while you are editing your settings as well.

Our first view is going to be a static JSON file. We’ll make a templates directory within our new app folder and add our JSON file there.

Edit your hello.json file and add the first action for your NCCO

In the code above we are defining a new list which contains a single talk action which will use text-to-speech to read out the text string to our caller whenever they answer our outbound call. We still need to render this file whenever we receive a GET request on our specified route, Django’s generic TemplateView is perfect for this. As we’re not extending the TemplateView, we can directly import it into our tts/urls.py

Once you’ve edited your urls.py start your Django server and check it is all working by visiting http://127.0.0.1:8000/hello/

Hopefully, you see the NCCO file we created above. If you don’t, check the browser debug screen or your terminal for any errors.

Before we can make our outbound call, we need our Django server to be reachable by the Nexmo API. We recommend using ngrok for this if you’re having problems read our blog post on connecting your local development server to the Nexmo API using a ngrok tunnel.

We’re going to need multiple terminals for the next part, so you might want to use screen or tmux. Ensure you still have your Django server running in one terminal and ngrok active in another. We’re going to make our first outbound call via the Python REPL, so run python in another terminal window, but don’t forget to activate your virtual environment first!

After running the commands above watch your ngrok terminal and you should see Nexmo requesting your NCCO! So that was a pretty simple example, let’s try sending a more exciting message.

Is that the best you can do?

Outbound call with dynamic data

This time we’re going to create our NCCO dynamically using information from the Marvel API. Before we get started on the next part, you’ll need to register for a free Marvel developer account; after registering I added my Marvel credentials as environmental variables.

These commands will create the environment variables in a UNIX system. However you will need to export them every time you restart your shell. You may want to use python-dotenv to make this automatic.

Let’s create a new route in our urls.py for this new NCCO endpoint.

In your views.py we will import and extend the TemplateView.

About our custom view

Looking at the code

Let’s go through what’s happening in our new MarvelView. We need to add two pieces of data available in our context when rendering our marvel.json template, voice_name and marvel_message. The voice_name is uncomplicated; it’s the name of a random English language synthesised voice from the selection offered by the Nexmo text-to-speech API. For the marvel_message we query the Marvel API for all characters in the Avengers (2016 – present) series. After tidying up the data slightly; removing any errant HTML tags, ignoring characters with missing information. We concatenate the character’s name and their description into a single string; this is our marvel_message.

If we tried to access http://127.0.0.1:8000/marvel/ now, we’d get a TemplateDoesNotExist exception. In our templates folder, we need to create a marvel.json

Now we can test our new endpoint, and hopefully, we should see some information on a random Avengers character! Data provided by Marvel. © 2014 Marvel

Avengers Assemble!

Making our outbound Avengers text-to-speech call

This time instead of using the Python REPL to make our call we’ll wrap it in a management command so we can quickly make an outbound Marvel call to any number. Django management commands require a particular directory structure, let’s create that first.

Now we have the files in place we can write our marvel.py

This code is essentially the same as what we did before on the REPL, but now we’ve wrapped it in a Django management command. The new marvel command takes two arguments; the number we want to call, and the Nexmo virtual number from which the call should originate.

screencast of the Marvel command making a call

What’s next?

What's next?

When you have an urgent alert, text-to-speech calls are perfect, but sometimes it’s not enough to just know that someone has answered the call. Combine outbound text-to-speech with IVR to ensure that they’ve received the message.

Tags: , , ,

Categorised in: , ,

This post was written by