2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
目的
本資料は、Pythonを使って、コミュニケーションAPIであるTwilioを学習するコンテンツとなっています。
コンテンツは以下の5つで構成されています。
- Lesson 1. RestAPIを使って、電話をかけてみる
- Lesson 2 オリジナルのメッセージを流してみる
- Lesson 3. ブラウザを電話機にしてみる
- Lesson 4. 音声認識した内容をSMSで送信
- Lesson 5. FAXの送受信
Twilioの概要は以下のサイトを御覧ください。
https://twilio.kddi-web.com
準備
Python
今回はPython3.xを利用しますので、Python3の実行環境(作業フォルダ)をご用意ください。
Pythonのバージョンを調べるには、以下のコマンドを利用します。
$ python --version
Python 3.7.2
ライブラリのインストールにはpipを利用しますので、Pythonと併せてpipも使えるようにしておいてください。
https://pip.pypa.io/en/stable/installing/
ngrok
Twilioを利用するためには、Twilioからアクセスが可能な公開サーバーが必要です。今回はサーバーは構築せず、ngrokを使ってローカルの環境を外部からアクセスできるようにします。
ngrokは以下のサイトからダウンロードして展開しておきます。
https://ngrok.com/
Twilio
Twilioのアカウントを保有していない場合は、まずはトライアルアカウントを取得してください。
無料サインアップの方法は、こちらの記事を参考にしてください。
[最新版]Twilioのサインアップ
トライアルアカウントでは、電話番号が1つだけ購入できます。また、発信先にはサインアップ時に利用した認証済み電話番号のみが利用できます。任意の電話番号に電話をかけたい場合や、複数の電話番号を購入したい場合は、支払情報(カード情報)を登録して、ポイントを購入してください。
※この記事のLesson 4からは、電話番号が2つ必要になります。
Lesson 1 RestAPIを使って、電話をかけてみる
このレッスンでは、まずTwilioの管理コンソールを使って、電話番号1つ購入します。その後、Pythonヘルパーライブラリをインストールし、電話をかけるコードを書きます。
現在、日本の電話番号を購入するためには、予め住所情報を登録しておく必要があります。住所情報の登録方法は、以下の記事を参考にしてください。
Twilio上で電話番号に住所を登録する方法
電話番号を購入
-
Twilioの管理コンソールにログインします。
https://www.twilio.com/login/kddi-web -
国に「Japan(+81)」が選択されていることを確認、さらに「音声通話」と「Fax」にチェックをして、検索ボタンを押します。
-
表示されたリストの中から1つを選択し、「購入」ボタンを押します。
-
Congratulationsダイアログが出たら番号の購入が完了です。「閉じる」ボタンを押してダイアログを閉じます。
後ほど利用するため、番号をメモ帳に控えておきます。
Pythonヘルパーライブラリの準備
Twilioには、Python用のヘルパーライブラリが用意されていますので、まずはそちらをインストールします。
$ pip install twilio
2019/9/24現在の最新バージョンは6.31.0です。これより低いバージョンがインストールされている場合は、-Uオプションをつけてインストールしてください。
なお、最新バージョンは、以下のサイトにあります。
https://github.com/twilio/twilio-python/
AccountSidとAuthTokenを調べる
-
Twilioの管理コンソールにログインします。
https://www.twilio.com/login/kddi-web -
Console DashboardのAccount Summaryに表示されている、ACCOUNT SIDとAUTH TOKENの値をメモ帳にコピーしておきます。
AUTH TOKENはマスクされていますが、目のアイコンを押すことで表示されます。
コーディング
- エディタを開き、以下のコードをコピペします。
from twilio.rest import Client
account_sid = "ACxxxxxxxxx" # Your Account SID from www.twilio.com/console
auth_token = "xxxxxxxx" # Your Auth Token from www.twilio.com/console
client = Client(account_sid, auth_token)
call = client.calls.create(
to="+81xxxxxxx",
from_="+81xxxxxxx",
url="http://demo.twilio.com/docs/voice.xml"
)
print(call.sid)
- account_sidには、先程控えておいたAccountSidを記入します。
- auth_tokenには、先ほど控えておいたAuthTokenを記入します。
- toには、ご自分の電話番号をE.164形式で記入します。(例: +819012345678)
- from_には、先程購入した電話番号をE.164形式で記入します。
- Pythonが実行できるフォルダ内に、call.pyという名前で保存します。
実行
- call.pyを実行して、ご自分の電話に電話がかかってくることを確認します。
$ python call.py
解説
先程のコードを確認しましょう。
電話をかけるには、calls.createを呼び出します。この中に発信元(from_)[fromは予約語で使えないので、from_になります]と発信先(to)を指定しています。
ポイントはurlで指定をしている部分です。ここには、相手が応答した際にどのようなことを実行するかを指示するためのXML(TwiMLと呼びます)を指定します。
今回指定したTwiMLは以下のようなXMLファイルになっています。
<Response>
<Say voice="alice">Thanks for trying our documentation. Enjoy!</Say>
<Play>http://demo.twilio.com/docs/classic.mp3</Play>
</Response>
動詞は、Text to Speech(文字を音声に変換)を実行し、ここで指定した文字列(Thanks for trying our documentation. Enjoy!)が音声として再生されます。
動詞は、音声ファイルを再生する動詞です。
このように、いくつかのTwiMLを組み合わせることでTwilioに対して動作を指定することができます。
Lesson 2 オリジナルのメッセージを流してみる
このレッスンでは、自分でオリジナルのメッセージを流すようにしてみます。そのためには、流したいメッセージを記載したTwiMLを作成し、Twilioからhttpもしくはhttpsでアクセスできる場所に配置する必要があります。
どのようなTwiMLがあるかは、以下のURLにドキュメントがあります。
https://www.twilio.com/docs/api/twiml
Flaskのインストール
Twilioからアクセスできるようにするために、今回はWebフレームワークとしてFlaskを利用します。
Flaskは以下の手順でインストールできます。
$ pip install Flask
TwiMLを返却するプログラムをFlaskで作成する
- エディタを開き、以下のコードをコピペします。
# say.py
from flask import Flask
from twilio.twiml.voice_response import VoiceResponse
app = Flask(__name__)
@app.route('/say', methods=['GET', 'POST'])
def say():
# TwiMLを作成
resp = VoiceResponse()
resp.say("こんにちは。トゥイリオってとても楽しいですね。", language="ja-JP", voice="alice")
return str(resp)
if __name__ == "__main__":
app.run(port=5000, debug=True)
- say.pyという名前で保存します。
- 実行してみます。
$ python say.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 219-682-997
- ブラウザを開き、「http://localhost:5000/say」と入力します。
上記のようなメッセージが表示されれば、とりあえずPythonのコードは正常です。
ngrokの起動
作成したPythonプログラムを外部に公開するために、ngrokを利用します。
- 以下のコマンドでngrokを起動します。
$ ngrok http 5000
- Forwardingのhttps側のURLをメモ帳にコピーしておきます。
発信プログラムを修正
- 先程作成したCall.pyをエディタで開きます。
from twilio.rest import Client
account_sid = "ACxxxxxxxxxxx" # Your Account SID from www.twilio.com/console
auth_token = "xxxxxxxxxxxx" # Your Auth Token from www.twilio.com/console
client = Client(account_sid, auth_token)
call = client.calls.create(
to="+81xxxxxxxxxx",
from_="+8150xxxxxxxx",
url="https://xxxxxxx.ngrok.io/say"
)
print(call.sid)
- urlの欄を先程メモしたURLに書き換えます。最後に/sayを付けるのを忘れないようにしてください。
テスト
- Lesson1と同様に、call.pyを実行してみます。
$ python call.py
- 電話がかかってきて、日本語でメッセージが流れれば成功です。
解説
Say.pyでは、オリジナルのTwiMLを作成しています。
TwilioのPythonヘルパーライブラリーを使うと、TwiMLも簡単に作成することができます。Voice系のTwiMLを作成するためには、twilio.twiml.voice_responseを予めimportしておきます。
日本語を話させるためには、language='ja-JP'とvoice='alice'を指定します。あまり長い文章を記述すると、正しく発声されないことがあるため、そのような場合はSay動詞を複数に分けて記載するようにします。
あと、このサンプルだと日本語がたどたどしい感じがしますね。流暢な日本語を話させたい場合は、TwiMLを生成する部分で、voiceパラメータに「Polly.Mizuki」や「Polly.Takumi」を使うと(以下のコードを参照)、比較的きれいな日本語で話してくれます。少しだけお金がかかりますが、きれいな日本語を使いたい人はぜひチャレンジしてみてください。
〜略〜
def say():
# TwiMLを作成
resp = VoiceResponse()
resp.say("こんにちは。トゥイリオってとても楽しいですね。", language="ja-JP", voice="Polly.Mizuki")
return str(resp)
〜略〜
これ以外にも、例えばエーアイさんの音声合成技術などを組み合わせることもできます。
- 株式会社エーアイ「AITalk」
Lesson 3. ブラウザを電話機にしてみる
ちょっと何を言っているかわからない人もいるかと思いますが、実はTwilioを使うと、みなさんが普段使っているブラウザを電話機として利用することができます。そう、ブラウザで電話ができるんです。
このレッスンでは、ブラウザを電話機として利用し、ブラウザ経由で電話をかけてみます。
ブラウザ経由での受発信は、Twilio Clientと呼ばれる機能を利用しますが、受発信のためにはアクセストークンという仕組みが必要となります。アクセストークンとは、Twilioを利用して電話の機能を使わせるための認証キーのことで、ユーザ側からTwilioに対してアクセストークンの発行依頼をかけることで取得できます。
これらの仕組みを1から作成するのは時間がかかるので、今回は予め用意されているクイックスタートを利用します。
このレッスンでも先程同様、ngrokを利用します。
プログラムのダウンロード
Gitが使える環境の場合は、以下のコマンドを使って作業ディレクトリにソースファイルをCloneしてください。
$ git clone https://github.com/TwilioDevEd/client-quickstart-python.git
Gitが使えない場合は、以下のURLからZipファイルをダウンロードして、作業ディレクトリに展開してください。
https://github.com/TwilioDevEd/client-quickstart-python/archive/master.zip
Cloneした(展開した)ディレクトリに移動します。
$ cd client-quickstart-python
.envファイルの設定
サンプルの.envファイルをコピーして、.envファイルを作成します。
$ cp .env.example .env
Windowsのユーザの方は、
$ cp .env.example.ps1 .env.ps1
.envもしくは、.env.ps1をエディタで開き、環境変数を設定します。
export TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
export TWILIO_AUTH_TOKEN=your_auth_token
export TWILIO_TWIML_APP_SID=APXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
export TWILIO_CALLER_ID=+1XXXYYYZZZZ
TWILIO_ACCOUNT_SIDとTWILIO_AUTH_TOKENには、前のレッスンで利用したAccountSitとAuthTokenを記載します。
TWILIO_TWIML_APP_SIDは、この時点ではまだわからないので放っておきます。
TWILIO_CALLER_IDには、購入した050番号をE.164形式で記載しておきます。
設定が済んだら、上書き保存しておきます。
環境変数の読み込み
以下のコマンドで環境変数を設定します。
$ source .env
Windowsユーザの方は、以下のコマンドで設定します。
. .\.env.ps1
ライブラリの読み込み
以下のコマンドを利用して、必要なライブラリを読み込みます。
$ pip install -r requirements.txt
なお、今回利用するライブラリは、Flask、twilio、fake-factoryの3つです。
ngrokを起動
$ ngrok http 5000
ngrokが起動したら、表示されるURL(httpsの方)をメモ帳に記録しておきます。
アプリケーションSIDの取得
- Twilioの管理コンソールにログインします。
- ボタンアイコンを押して、「プログラマブルVoice」を選択します。
- 「ツール」を選択します。
- プラスアイコンを押して、新しいTwiML Appsを作成します。
- フレンドリーネームに「Twilio Client Quickstart」と入力します。
- 音声通話のREQUEST URLに、先程記録したngrokのURL+/voiceを入力します。
例: https://xxxxxxx.ngrok.io/voice - 「保存」ボタンを押します。
-
控えたApplication SIDを、先程編集した.envのTWILIO_TWIML_APP_SIDに転記します。
-
起動していたアプリケーション(app.py)を一度終了します(Ctrl-C)。
-
環境変数を読み込み直します。
$ source .env
アプリケーションを実行
$ python app.py
テスト
画面のように、Twilio Device Ready! が表示されれば電話がかけられます。
発信する場合は、電話番号はE.164形式で指定します。
解説
app.pyをエディタで開いて確認をしてみます。
この中には大きく、/tokenというアクセストークンを取得するコードと、/voiceという電話をかけるコードの2つが記述されています。
/token内では、ClientCapbilityTokenオブジェクトを生成し、allow_client_outgoing(application_sid)とallow_client_incoming(identity)の2つを設定しています。前者が発信用のトークンの設定で、後者が着信用の設定になります。
発信用のトークンには、TwiML AppsのSIDを指定しており、これによって、ブラウザから発信の指示がきた場合に、Twilioが/voiceを呼ぶことになります。また、着信用のトークンでは、自分自身のidentityを設定しており、これによって、他のクライアントがidentityを宛先に指定することで電話が着信する仕組みを実現しています。
/voiceは、電話の発信時にTwilioから呼ばれるURLで、相手先番号がToパラメータとして渡されます。これをDial動詞として返却することで、Twilioが電話を掛けてくれます。
今回は、050番号での着信は実装されていませんが、もし実装したい場合は、Twilioの管理コンソールを使って、050番号の着信時処理を指定し、identityを宛先にしたDial動詞をTwiMLで返すようにすればOKです。
フロントエンド側のコードは、staticフォルダ内のquickstart.jsに記載されています。
ページがロードされると、ajaxを使ってアクセストークンを取得していることがわかります。トークンの取得に成功すると、取得したトークンを使ってDeviceを初期化します。初期化が完了すると、Device.readyイベントが発火します。
Deviceには、ready以外にもいくつか重要なイベントが用意されています。これらのイベントについては、以下のドキュメントに記載があります。
https://www.twilio.com/docs/api/client/device
Lesson 4. 音声認識した内容をSMSで送信
このレッスンでは、Twilioの音声認識技術とSMS送信技術を組み合わせて、050番号に着信したら、音声を記録して文字に変換した結果を発信者にSMSで返すプログラムを作成します。
SMSの送信には、050番号が使えないため、新たにUS番号を1つ購入します。Twilioのトライアルアカウントをアップグレードする必要があります。
US番号の購入
- Twilioの管理コンソールにログインします。
- ボタンアイコンから「電話番号」を選択します。
- 「Buy a Number」を選択し、国のリストボックスから「United States」を選択し、「検索」ボタンを押します。
- SMSが使えるローカル番号を一つ選択し、「購入」ボタンを押します。
- Buy This Numberダイアログが表示されたら、「Buy This Number」ボタンを押します。
- Congratulationsダイアログが表示されたら、「閉じる」ボタンを押します。
作業環境の構築とコーディング
- Pythonが利用できる作業ディレクトリに、callSMSという名前のディレクトリを作成し、そのディレクトリに移動します。
- app.pyという名前のファイルを作成し、以下のコードを貼り付けます。
# app.py
from flask import Flask, request, Response
from twilio.rest import Client
from twilio.twiml.voice_response import Gather, VoiceResponse, Say
app = Flask(__name__)
account_sid = "ACxxxxxxxxxxxxxxxxxxxxxx"
auth_token = "xxxxxxxxxxxxxxxxxxxxxxx"
client = Client(account_sid, auth_token)
@app.route('/calling', methods=['GET', 'POST'])
def calling():
# 電話が着信した時に呼ばれるWebHook
response = VoiceResponse()
gather = Gather(input='speech', language='ja-JP', action='/sendsms', method='POST')
gather.say('お電話ありがとうございます。メッセージをどうぞ。', language='ja-JP', voice='alice')
response.append(gather)
return str(response)
@app.route('/sendsms', methods=['POST'])
def sendsms():
# 音声認識結果を取得する
result = request.form["SpeechResult"] or ''
to = request.form["From"] or ''
if (result != '' and to != ''):
# SMSを送信する
message = client.messages.create(to=to,
from_="+1XXXXXXXXXXXX",
body=result)
print(message.sid)
resp = VoiceResponse()
resp.say("メッセージをお送りしました。ありがとうございます。", language="ja-JP", voice="alice")
return str(resp)
else:
resp = VoiceResponse()
resp.say("申し訳ございません。音声認識ができませんでした。", language="ja-JP", voice="alice")
return str(resp)
if __name__ == "__main__":
app.run(port=5000, debug=True)
- account_sidとauth_tokenをご自分のものに書き換えます。
- from_の電話番号を先程購入したUSの番号に書き換えます。
アプリケーションの起動
$ python app.py
ngrokの起動
$ ngrok http 5000
ngrokが起動したら、httpsから始まるURLを記録しておきます。
050番号の着信設定
- Twilio管理コンソールにログインします。
- ボタンアイコンを押して、「電話番号」を選択します。
- 購入した050番号を選択して設定画面を開きます。
- A CALL COMES IN欄を「Webhook」にし、ngrokの起動時に控えておいたURLに/calllingを付加したものを記述します。
- 「保存」ボタンを押して設定を保存します。
テスト
- 着信設定を行った050番号に電話を掛けて、ガイダンスの後にメッセージを吹き込みます。
- しばらくするとメッセージを送ったというガイダンスが流れ、SMSに音声認識結果が送られてきます。
解説
callingの方で生成したGather動詞は、本来DTMF信号(プッシュトーン信号)を処理するための動詞ですが、DTMF以外に音声データを取得することもできます。音声データは、内部的に音声認識エンジンに渡って、その結果がactionパラメータで指定したWebhookに流れてきます。
音声は最大60秒まで録音が可能で、通話料とは別に変換1回(15秒単位)につき、3円の追加料金が発生します。
今回は音声認識後にそのままSMSを送信しましたが、たとえばIBM Watsonの会話APIなどを利用することで、音声を使ったBOTを作ることも可能です。
Lesson 5. FAXの送受信
このレッスンでは、Programmable FAXの機能を使って、FAXの送受信を実現します。世界的に見ると日本は未だにFAXがかなり使われている国で、プログラムからFAXを送れたり、また受信したFAXを自動的に処理したりするなど、使い方は色々と考えられます。
FAXの送受信には050番号が使えますが、同じ050番号で音声着信とFAX受信はできません。今回はすでに購入済みの050番号をFAX用に切り替えて使用します。
プログラムのダウンロードと設定ファイルの更新
- GitHubからサンプルプログラムをCloneします。
$ git clone https://github.com/twilioforkwc/simpleFAX.git
$ cd simpleFAX
- example.envを.envに名前を変えます。
$ mv example.env .env
- .envファイルを編集し、ACCOUNT_SID、AUTH_TOKENをご自分の環境に併せて編集します。
- FROMには、購入した050番号、TOには、送信先のFAX番号を記載します。なお、送信先のFAX番号は、送信時に指定することもできます。
- 環境変数を設定します。
$ source .env
アプリケーションの実行
- アプリケーションを実行します。
$ python app.py
- ngrokを起動します。
$ ngrok http 3000
起動したhttpsのURLを控えます。
050番号の設定
- Twilioの管理コンソールにログインします。
- ボタンアイコンをクリックし、電話番号を選択します。
- 購入済みの050番号を選択します。
- ACCEPT INCOMINGを「Faxes」に切り替えます。
- A FAX COMES INを、先程控えておいたngrokのURLに/receiveを付加したものに書き換えます。
- 「保存」ボタンを押して、設定を完了します。
テスト
- 購入した050番号に対して、FAX機からFAXを送ってみます。
- 成功するとFAXフォルダにPDFファイルが作成されます。
- FAXを送るには、ブラウザのURL欄に、ngrokのURL/sendfaxと入力します。送信先のFAX番号は.envで指定したものが利用されますが、変更したい場合は、URLにtoパラメータを付加することができます。また、送信するPDFはstaticフォルダに入っているsample.pdfが利用されますが、別のファイルを送信したい場合は、URLにpdfパラメータを付加することができます。なお、送りたいFAXは予めstaticフォルダに入れておく必要があります。
例: https://xxxxxx.ngrok.io/sendfax?to=03XXXXXXXX&pdf=xxxxxx.pdf
解説
app.pyには大きく、送信用のコード(sendfax)と、受信用のコード(receive、actionReceiver)の2つが記載されています。
送信用のsendfaxでは、RestAPIを使ってFAXを送信するコードが記載されています。現時点ではPython用のヘルパーライブラリはFAXに対応していないため、requestsライブラリを使って実現しています。
送信が成功したかどうかは、送信時のRestAPIでstatusCallbackを指定するか、送信時のRestAPIの戻り値に含まれるFAX SIDを使ってさらにRestAPIを呼ぶ必要がありますが、本プログラムではその処理は省略しています。
受信用のreceiveは、Twilioの番号にFAXが着信した時に最初に呼ばれるWebhookになります。ここでは、動詞(受信する場合)か、動詞(拒否する場合)のいずれかを返す必要があります。今回は受信したいので、動詞を返却しています。
動詞には、actionパラメータが指定でき、受信が完了もしくは失敗したときに呼び出されます。今回のコードでは、actionReceiverが該当します。
actionReceiverの中では、受信が成功したかを判断し、成功した場合はMediaUrlにかかれているPDFファイルをFAXフォルダにダウンロードしています。
Programmable FAXに関する詳しいドキュメントは、以下にあります。
https://www.twilio.com/docs/api/fax
まとめ
今回はPythonを使った場合のご紹介でしたが、Python以外にもNode.js、C#、Java、Ruby、PHP、Salesforceなどの言語用のSDKもご用意しています。
詳しくはこちらを御覧ください。
Twilio(トゥイリオ)とは
https://twilio.kddi-web.com
Twilioは音声通話、メッセージング(SMS/チャット)、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。