
Teilen Sie:
Aaron war ein Entwickler-Befürworter bei Nexmo. Aaron ist ein erfahrener Software-Ingenieur und Möchtegern-Digitalkünstler, der häufig Dinge mit Code oder Elektronik entwickelt, manchmal auch beides. Wenn er an etwas Neuem arbeitet, erkennt man das in der Regel am Geruch von brennenden Bauteilen in der Luft.
Ein Text-to-Speech-Telefonat mit Django führen
Lesedauer: 5 Minuten
Unter den unaufhörlichen Benachrichtigungen, die Menschen jeden Tag erhalten, ist ein klingelndes Telefon immer noch viel schwieriger zu ignorieren oder zu übersehen.

Es schafft ein Gefühl der Dringlichkeit und ist damit die perfekte Methode, um kritische oder zeitkritische Nachrichten zu übermitteln, wie z. B. Zwei-Faktoren-Authentifizierungscodes oder wichtige Service-Benachrichtigungen.
In diesem Tutorial werden wir uns ansehen, wie Sie folgende Funktionen nutzen können Nexmo's Text-to-Speech API für ausgehende Anrufe mit Python und Django nutzen kann.
Voraussetzungen
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
In diesem Lernprogramm wird auch eine virtuelle Telefonnummer verwendet. Um eine zu erwerben, gehen Sie zu Rufnummern > Rufnummern kaufen und suchen Sie nach einer Nummer, die Ihren Anforderungen entspricht.
Ihr Django-Server muss für die Nexmo-API erreichbar sein. Wenn Sie ihn lokal betreiben, dann müssen Sie ein Tool wie ngrok verwenden, um ihn dem öffentlichen Internet zugänglich zu machen.
Nexmo-Applikationen
Bevor wir mit dem Schreiben unseres Python/Django-Codes beginnen, müssen wir noch eine letzte Sache verstehen Nexmo-Applikationen. Wenn wir eine neue Nexmo-Applikation erstellen, verwenden wir sie nicht nur, um Konfigurationsdaten wie die URL unseres Nexmo-Aufrufsteuerungsobjekts (NCCO)oder die Adresse, an die Nexmo Ereignisinformationen senden soll, sondern auch, um unser öffentliches/privates Schlüsselpaar zu erzeugen.
Sicherheit ist für uns von entscheidender Bedeutung, und wir möchten nicht, dass sich jemand als Sie oder Ihre Anwendung ausgeben kann, indem er Anrufe von Ihrer Nummer tätigt. Um unsere Voice API zu sichern, verwenden wir daher Ihren privaten Schlüssel, um ein JSON-Web-Token (JWT).
Bevor wir also beginnen, lassen Sie uns eine neue Nexmo-Anwendung erstellenerstellen, diese mit einer virtuellen Nummer verbinden und dann unseren privaten Schlüssel generieren und herunterladen.

Denken Sie daran, Ihren privaten Schlüssel sicher aufzubewahren; ich empfehle ein Programm wie Tresor. Wenn Sie aus irgendeinem Grund glauben, dass jemand Ihren privaten Schlüssel kompromittiert hat, sollten Sie ihn sofort nicht mehr verwenden und ein neues Paar aus öffentlichem und privatem Schlüssel erstellen.
Erstellung eines grundlegenden NCCO
Die outbound voice API erfordert eine answer_url. Wenn jemand unseren Anruf entgegennimmt, wird Nexmo unsere NCCO-Datei von dieser URL abrufen und alle darin definierten Aktionen ausführen. Lassen Sie uns eine Django-Anwendung erstellen, damit wir unsere NCCO JSON-Datei ausliefern können.
Wir werden unsere Abhängigkeiten über pip installieren. Ich würde immer empfehlen jedes Python-Projekt und seine Abhängigkeiten in seiner eigenen virtuellen Umgebung zu halten.
pip install django nexmo
django-admin startproject ttsSobald wir unser Django-Projekt haben, müssen wir eine neue App erstellen, in der der Großteil unserer Entwicklung stattfindet.
cd tts
python manage.py startapp outboundNachdem Sie Ihre neue Anwendung erstellt haben, vergessen Sie nicht, sie zu Ihrer Datenbank hinzuzufügen. tts/settings.pyhinzuzufügen, sollten Sie wahrscheinlich auch Ihre ALLOWED_HOSTS bearbeiten, während Sie Ihre Einstellungen bearbeiten.
INSTALLED_APPS = [
…
'outbound'
]
ALLOWED_HOSTS = ["*"] # Never do this in production!Unsere erste Ansicht wird eine statische JSON-Datei sein. Wir erstellen ein Vorlagenverzeichnis in unserem neuen App-Ordner und fügen dort unsere JSON-Datei hinzu.
mkdir -p outbound/templates/outbound
touch outbound/templates/outbound/hello.jsonBearbeiten Sie Ihre hello.json Datei und fügen Sie die erste Aktion für Ihr NCCO hinzu
[
{
"action": "talk",
"text": "Hello World from Nexmo"
}
]Im obigen Code definieren wir eine neue Liste, die eine einzelne talk Aktion enthält, die mithilfe von Text-to-Speech die text vorliest, wenn der Anrufer unseren ausgehenden Anruf entgegennimmt. Wir müssen diese Datei immer noch rendern, wenn wir eine GET Anfrage auf unserer spezifizierten Route erhalten, Djangos generische TemplateView ist perfekt dafür geeignet. Da wir nicht die TemplateViewnicht erweitern, können wir sie direkt in unsere tts/urls.py
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^hello/', TemplateView.as_view(
template_name='outbound/hello.json',
content_type='application/json'
)),
]Sobald Sie Ihre urls.py bearbeitet haben, starten Sie Ihren Django-Server und überprüfen Sie, ob alles funktioniert, indem Sie http://127.0.0.1:8000/hello/
python manage.py runserverHoffentlich sehen Sie die NCCO-Datei, die wir oben erstellt haben. Falls nicht, überprüfen Sie den Debug-Bildschirm des Browsers oder Ihr Terminal auf Fehler.
Bevor wir unseren ausgehenden Anruf tätigen können, muss unser Django-Server für die Nexmo-API erreichbar sein. Wir empfehlen die Verwendung von ngrok für diese Aufgabe, wenn Sie Probleme haben Lesen Sie unseren Blog-Beitrag über die Verbindung Ihres lokalen Entwicklungsservers mit der Nexmo-API unter Verwendung eines ngrok-Tunnels.
ngrok http 8000Für den nächsten Teil werden wir mehrere Terminals benötigen, daher sollten Sie screen oder tmux verwenden. Stellen Sie sicher, dass Ihr Django-Server in einem Terminal läuft und ngrok in einem anderen aktiv ist. Wir werden unseren ersten ausgehenden Aufruf über die Python REPL machen, also führen Sie python in einem anderen Terminalfenster aus, aber vergessen Sie nicht, zuerst Ihre virtuelle Umgebung zu aktivieren!
import nexmo
client = nexmo.Client(application_id='<VOICE APP ID>', private_key='private.key')
to_number = [{'type': 'phone', 'number': '<YOUR NUMBER>'}]
from_number = {'type': 'phone', 'number': '<NEXMO VIRTUAL NUMBER>'}
answer_url = ['https://<NGROK URL>/hello/']
client.create_call({'to': to_number, 'from': from_number, 'answer_url': answer_url})
Nachdem Sie die obigen Befehle ausgeführt haben, beobachten Sie Ihr ngrok-Terminal und Sie sollten sehen, dass Nexmo Ihr NCCO anfordert! Das war also ein ziemlich einfaches Beispiel. Versuchen wir nun, eine spannendere Nachricht zu senden.

Ausgehender Anruf mit dynamischen Daten
Dieses Mal werden wir unser NCCO dynamisch erstellen, indem wir Informationen aus der Marvel-API. Bevor wir mit dem nächsten Teil beginnen, müssen Sie sich für ein kostenlosen Marvel Entwickler AccountNach der Registrierung habe ich meine Marvel-Anmeldedaten als Umgebungsvariablen hinzugefügt.
export MARVEL_API_KEY='<YOUR API KEY>'
export MARVEL_PRIVATE_KEY='<YOUR PRIVATE KEY>'
Mit diesen Befehlen werden die Umgebungsvariablen in einem UNIX-System erstellt. Sie müssen sie jedoch jedes Mal exportieren, wenn Sie Ihre Shell neu starten. Vielleicht möchten Sie python-dotenv verwenden, um dies zu automatisieren.
Erstellen wir eine neue Route in unserem urls.py für diesen neuen NCCO-Endpunkt.
from django.conf.urls import url
from django.views.generic import TemplateView
from outbound.views import MarvelView
urlpatterns = [
url(r'^hello/', TemplateView.as_view(
template_name='outbound/hello.json',
content_type='application/json'
)),
url(r'^marvel/', MarvelView.as_view())
]In Ihrem views.py importieren und erweitern wir die TemplateView.
import os
from hashlib import md5
from time import time
import random
import requests
from django.utils.html import strip_tags
from django.views.generic import TemplateView
class MarvelView(TemplateView):
template_name = 'outbound/marvel.json'
content_type = 'application/json'
@staticmethod
def get_marvel_data():
marvel_api_url = 'https://gateway.marvel.com:443/v1/public/characters'
private_key = os.environ['MARVEL_PRIVATE_KEY']
api_key = os.environ['MARVEL_API_KEY']
# Create Marvel API request params
timestamp = str(time())
hashed_key = md5(
str(timestamp + private_key + api_key).encode('utf-8')
)
# Fetch Avengers data from Marvel API
response = requests.get(
marvel_api_url,
params={
'series': '22547', # Avengers (2016 - Present)
'apikey': api_key,
'ts': timestamp,
'hash': hashed_key.hexdigest()
},
headers={
'Accept': 'application/json'
}
)
marvel_response_data = response.json()
# Some characters don't have descriptions, ignore those characters
return [{
'name': x['name'],
'description': x['description']
} for x in marvel_response_data['data']['results'] if x['description']]
@staticmethod
def random_voice_name():
# https://developer.nexmo.com/api/voice/ncco#voice-names
return random.choice([
'Salli', 'Joey', 'Nicole', 'Russell', 'Amy', 'Brian', 'Emma',
'Gwyneth', 'Geraint', 'Raveena', 'Chipmunk', 'Eric', 'Ivy',
'Jennifer', 'Justin', 'Kendra', 'Kimberly',
])
# Add our Marvel data to the templete context
def get_context_data(self, **kwargs):
marvel_data = self.get_marvel_data()
random_character = random.choice(marvel_data)
kwargs['voice_name'] = self.random_voice_name()
# Concat our character name & bio together to act as our voice message
# Also remove any errant HTML tags from Marvel text
kwargs['marvel_message'] = "{name} - {description}".format(
name=strip_tags(random_character['name']),
description=strip_tags(random_character['description'])
)
return super(MarvelView, self).get_context_data(**kwargs)
Über unsere benutzerdefinierte Ansicht

Schauen wir uns an, was in unserem neuen MarvelView. Wir müssen zwei Daten hinzufügen, die in unserem Kontext verfügbar sind, wenn wir unsere marvel.json Vorlage, voice_name und marvel_message. Die voice_name ist unkompliziert; es ist der Name einer zufälligen englischsprachigen synthetisierten Stimme aus der Auswahl, die von der Nexmo Text-to-Speech API angeboten wird. Für die marvel_message fragen wir die Marvel-API nach allen Charakteren aus der Avengers (2016 - heute) Serie. Nachdem wir die Daten ein wenig aufgeräumt haben, entfernen wir alle fehlerhaften HTML-Tags und ignorieren Zeichen mit fehlenden Informationen. Wir verketten den Namen des Charakters und seine Beschreibung zu einer einzigen Zeichenkette; dies ist unser marvel_message.
Wenn wir jetzt versuchen würden, auf http://127.0.0.1:8000/marvel/ zuzugreifen, würden wir eine TemplateDoesNotExist Ausnahme. In unserem Vorlagenordner müssen wir eine marvel.json
[
{
"action": "talk",
"text": "{{ marvel_message|safe }}",
"voiceName": "{{ voice_name }}"
}
]Jetzt können wir unseren neuen Endpunkt testen, und hoffentlich werden wir einige Informationen über einen zufälligen Avengers-Charakter sehen! Daten zur Verfügung gestellt von Marvel. © 2014 Marvel
[
{
"action": "talk",
"text": "Taskmaster - Taskmaster first exhibited his unusual ability, called 'photographic reflexes,' which allowed him to mimic the motion of anyone he saw, when he was a young boy.",
"voiceName": "Emma"
}
]
Unser ausgehender Avengers-Text-to-Speech-Anruf
Dieses Mal verwenden wir nicht die Python REPL, um unseren Anruf zu tätigen, sondern verpacken ihn in einen Verwaltungsbefehl, damit wir schnell einen ausgehenden Marvel-Anruf an eine beliebige Nummer tätigen können. Django-Verwaltungsbefehle erfordern eine bestimmte Verzeichnisstruktur, die wir zuerst erstellen.
mkdir -p outbound/management/commands
touch outbound/management/__init__.py
touch outbound/management/commands/__init__.py
touch outbound/management/commands/marvel.pyJetzt, wo die Dateien vorhanden sind, können wir unsere marvel.py
import nexmo
from django.core.management.base import BaseCommand
class Command(BaseCommand):
help = 'Random Avenger character as a TTS phonecall'
def add_arguments(self, parser):
parser.add_argument('to_number', type=str)
parser.add_argument('from_number', type=str)
def handle(self, *args, **options):
client = nexmo.Client(
application_id='<YOUR NEXMO VOICE APP ID>',
private_key='private.key'
)
to_number = [{'type': 'phone', 'number': options['to_number']}]
from_number = {'type': 'phone', 'number': options['from_number']}
answer_url = ['https://<NGROK URL>/marvel/']
response = client.create_call({
'to': to_number,
'from': from_number,
'answer_url': answer_url
})
self.stdout.write(str(response))
Dieser Code ist im Wesentlichen derselbe, den wir zuvor in der REPL verwendet haben, aber jetzt haben wir ihn in einen Django-Verwaltungsbefehl verpackt. Der neue marvel Befehl nimmt zwei Argumente entgegen: die Nummer, die wir anrufen wollen, und die virtuelle Nexmo-Nummer, von der der Anruf ausgehen soll.

Was kommt als Nächstes?

Wenn Sie eine einen dringenden Alarmsind Text-to-Speech-Anrufe perfekt, aber manchmal reicht es nicht aus, nur zu wissen, dass jemand den Anruf entgegengenommen hat. Kombinieren Sie ausgehende Text-to-Speech-Anrufe mit IVR um sicherzustellen, dass der Anrufer die Nachricht erhalten hat.
Teilen Sie:
Aaron war ein Entwickler-Befürworter bei Nexmo. Aaron ist ein erfahrener Software-Ingenieur und Möchtegern-Digitalkünstler, der häufig Dinge mit Code oder Elektronik entwickelt, manchmal auch beides. Wenn er an etwas Neuem arbeitet, erkennt man das in der Regel am Geruch von brennenden Bauteilen in der Luft.
