https://a.storyblok.com/f/270183/601381/4325448037/tts-superhero.png

Djangoで音声合成電話をかける

最終更新日 August 14, 2017

所要時間:1 分

毎日絶え間なく届く通知のなかでも、電話の着信音は無視したり見過ごしたりするのが難しい。

Tony Stark looking stressed

切迫感を与えることで、以下のような重要なメッセージや一刻を争うメッセージを配信するのに最適な方法となる。 二要素認証コードまたは 重要なサービス通知.

このチュートリアルでは Nexmo の音声合成 APIを使って Python と Django で発信する方法を説明します。

前提条件

あなたの Django サーバが Nexmo API から到達可能である必要があります。ローカルで動かしている場合は ngrok のようなツールを使って公開する必要があります。.

Nexmoアプリケーション

Python/Djangoのコードを書き始める前に、もうひとつ理解しておきたいことがあります。 Nexmoアプリケーション.新しい Nexmo アプリケーションを作成するとき、Nexmo アプリケーションの URL のような設定データを保存するために使うだけでなく、Nexmo アプリケーションを作成する前に、Nexmo アプリケーションについて理解しておく必要があります。 Nexmoコールコントロールオブジェクト(NCCO)また、公開鍵と秘密鍵のペアを生成するためにも使うことができます。

私たちにとってセキュリティは非常に重要であり、あなたの番号から電話をかけることで、あなたやあなたのアプリケーションになりすますことができないようにしています。そのため、Voice APIを保護するために、お客様の秘密鍵を使用して JSONウェブトークン(JWT).

では始める前に 新しいNexmoアプリケーションを作成しを作成し、バーチャル番号にアタッチし、秘密鍵を生成してダウンロードしましょう。

Voice application creation screencast

秘密鍵を安全に保管することを忘れないでください。 ボールト.もし何らかの理由で秘密鍵が漏洩したと思われる場合は、直ちに使用を中止し、新しい公開鍵と秘密鍵のペアを生成してください。

基本的なNCCOの作成

を使用します。 アウトバウンド Voice APIには answer_url.誰かが電話に出ると、NexmoはこのURLからNCCOファイルを取得し、そこで定義されたアクションを実行します。Django アプリケーションを作成して、NCCO JSON ファイルを提供できるようにしましょう。

pipを使って依存関係をインストールする。私は常に 各 Python プロジェクトとその依存関係をそれぞれの仮想環境に置いておくことをお勧めします。.

pip install django nexmo
django-admin startproject tts

Django プロジェクトができたら、新しいアプリを作成する必要があります。

cd tts
python manage.py startapp outbound

新しいアプリケーションを作成したら、そのアプリケーションをあなたの tts/settings.pyに追加することを忘れないでください。 ALLOWED_HOSTSを編集する必要があるでしょう。

INSTALLED_APPS = [

    'outbound'
]
ALLOWED_HOSTS = ["*"] # Never do this in production!

最初のビューは静的なJSONファイルにします。新しいアプリフォルダ内にtemplatesディレクトリを作成し、そこにJSONファイルを追加します。

mkdir -p outbound/templates/outbound
touch outbound/templates/outbound/hello.json

ファイルを編集し hello.jsonファイルを編集し、NCCOの最初のアクションを追加する。

[
    {
        "action": "talk",
        "text": "Hello World from Nexmo"
    }
]

上記のコードでは、新しいリストを定義しています。 talkアクションを定義しています。 text文字列を読み上げます。指定したルートでリクエストを受け取るたびに、このファイルをレンダリングする必要があります。 GETリクエストを受け取るたびに、このファイルをレンダリングする必要があります。 TemplateViewはこれに最適です。を拡張していないので TemplateViewを拡張していないので、直接 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'
    )),
]

を編集したら urls.pyを編集したら、Django サーバを起動し、次のようにアクセスして動作していることを 確認してください。 http://127.0.0.1:8000/hello/

python manage.py runserver

うまくいけば、上で作成したNCCOファイルが表示されるはずだ。表示されない場合は、ブラウザーのデバッグ画面かターミナルでエラーがないか確認してください。

アウトバウンドコールを行う前に、Django サーバが Nexmo API から到達可能である必要があります。もし問題があれば、ngrok を使うことをお勧めします。 ngrok tunnel を使ってローカルの開発サーバを Nexmo API に接続する方法についてのブログ記事を参照してください。.

ngrok http 8000

次のパートでは複数の端末が必要になるので、 screen や tmux を使うと良いでしょう。一つの端末で Django サーバを動かし、別の端末で ngrok をアクティブにしてください。Python REPL 経由で最初のアウトバウンドコールを行います。 pythonを別のターミナルウィンドウで実行してください!

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})

上記のコマンドを実行した後、ngrokターミナルを見ると、NexmoがあなたのNCCOをリクエストしているのが見えるはずです!では、もっとエキサイティングなメッセージを送ってみましょう。

Is that the best you can do?

ダイナミック・データによるアウトバウンドコール

今回は、以下の情報を使って動的にNCCOを作成する。 Marvel API.次のパートを始める前に、無料の に登録する必要がある。登録後、私はMarvelの認証情報を環境変数として追加した。

export MARVEL_API_KEY='<YOUR API KEY>'
export MARVEL_PRIVATE_KEY='<YOUR PRIVATE KEY>'

これらのコマンドはUNIXシステムの環境変数を作成する。しかし、シェルを再起動するたびにそれらをエクスポートする必要がある。あなたは python-dotenvを使うと良いでしょう。

に新しいルートを作成しよう。 urls.pyに新しいルートを作成しよう。

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())
]

あなたの views.pyをインポートして拡張します。 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)

カスタムビューについて

Looking at the code

私たちの新しい仕事について説明しよう。 MarvelView.テンプレートをレンダリングするときに、コンテキストで利用可能な2つのデータを追加する必要があります。 marvel.jsonテンプレートをレンダリングするときに voice_namemarvel_message.は単純である。 voice_nameは単純で、Nexmo音声合成APIが提供する音声の中から、ランダムに合成された英語の音声の名前です。 Nexmoの音声合成APIが提供する選択肢の中から、ランダムな英語の合成音声の名前です。.については marvel_messageについては、Marvel APIに、以下のシリーズに登場するすべてのキャラクターを問い合わせる。 アベンジャーズ (2016 - 現在) シリーズ.誤ったHTMLタグを削除し、情報が欠落しているキャラクターを無視する。キャラクターの名前と説明を1つの文字列に連結します。 marvel_message.

今、http://127.0.0.1:8000/marvel/ にアクセスしようとすると、例外が発生する。 TemplateDoesNotExist例外が発生します。テンプレート・フォルダーに marvel.json

[
    {
        "action": "talk",
        "text": "{{ marvel_message|safe }}",
        "voiceName": "{{ voice_name }}"
    }
]

これで、新しいエンドポイントをテストすることができる。うまくいけば、ランダムなアベンジャーズのキャラクターに関する情報を見ることができるだろう! データ提供:マーベル© 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"
    }
]

Avengers Assemble!

アベンジャーズのアウトバウンド音声合成電話をかける

今回は、Python REPL を使って電話をかける代わりに、管理コマンドでそれをラッ プして、任意の番号に Marvel の発信電話を素早くかけられるようにします。Django の管理コマンドは特定のディレクトリ構造を必要とします。

mkdir -p outbound/management/commands
touch outbound/management/__init__.py
touch outbound/management/commands/__init__.py
touch outbound/management/commands/marvel.py

これでファイルが揃ったので、あとは 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))

このコードは基本的に、以前 REPL でやったことと同じですが、今回は Django の管理コマンドにラッピングしました。新しい marvelコマンドは2つの引数を取ります; 電話をかけたい番号と、電話の発信元となる Nexmo のバーチャル番号です。

Screencast of the Marvel command making a call

次はどうする?

What's next?

緊急警報 緊急アラート音声合成は完璧ですが、誰かが電話に出たというだけでは不十分な場合もあります。 発信音声合成とIVRを組み合わせてと組み合わせることで、相手がメッセージを受け取ったことを確認できます。

シェア:

https://a.storyblok.com/f/270183/150x150/a3d03a85fd/placeholder.svg
Aaron Bassettヴォネージの卒業生

アーロンはNexmoの開発者支持者だった。ベテランのソフトウェア・エンジニアであり、デジタル・アーティスト志望でもあるアーロンは、コードや電子機器、時にはその両方を使って何かを作っているところをよく見かける。彼が何か新しいことに取り組んでいるときは、空気中の部品が燃える匂いでわかるのが通例だ。