Twilioブログ

【Twilio講座 入門編⑥】Programmable Voiceの使い方|自動音声応答IVRを作ってみよう!

前回のTwilio講座 入門編⑤では、Twilioのメイン機能である「Programmable Voice」の基本情報についてご紹介しました。

今回のTwilio講座 入門編⑥では、実際にProgrammable Voiceの使い方についてご紹介いたします。

■Twilio講座 入門シリーズ■

【Twilio講座 入門編①】コミュニケーションAPIのTwilioとは?

【Twilio講座 入門編②】アカウントの種類と無料アカウント作成方法

【Twilio講座 入門編③】Twilio管理画面(コンソール)

【Twilio講座 入門編④】電話番号を購入するために必要な手続き

【Twilio講座 入門編⑤】Programmable Voiceとは?

【Twilio講座 入門編⑥】Programmable Voiceの使い方|自動音声応答IVRを作ってみる!

CTA_まずはtwilioを使ってみる。

目次

TwiMLについて

Twilioに指示を出す際、主に使うのが TwiML(トゥイムル)と呼ばれる専用のマークアップ言語です。専用言語といっても難しいものではなく、XML形式の分かりやすい書式になっています。

例:テキストを音声で喋らせるTwiML

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Say language="ja-JP">お電話ありがとうございます。本日は営業を終了しています。またのお電話お待ちしております。</Say>
</Response>

※TwiMLの書式や使える命令の詳しい情報は、ドキュメント(Twilio Docs)を参照してください。

※TwiMLを記載したテキストファイルは必ずUTF-8の文字コードで保存する必要があり、他の文字コードは利用できません。

先頭行の <?xml version="1.0" encoding="UTF-8"?> は定型文で、TwiMLの先頭は必ずこの1行から始めます。またTwilioへの命令部は<Response>で始まり</Response> で終わります。この中に命令一式を記述していきます。 

<Say language="ja-JP"> は、 </Say> までに囲まれたテキストを日本語の合成音声で話しなさい、という命令です。

TwiMLは上から下へ順番に処理されていくため、このTwiMLの例では、Sayをしたら「処理終了=電話が切れる」という動作になります。

TwiMLの「動詞」と「名詞」

<Response>に囲まれた動作命令を、TwiMLでは『動詞』と呼びます。上の例では『Say動詞』です。

一方、TwiMLには以下のような『名詞』も存在しています。

<Dial callerId="+8150 XXXXXX >
 <Number>+8190 XXXXXX </Number>
</Dial>

このうち、Dial が電話をかけるという命令で『Dial動詞』と呼びます。そしてDial動詞に囲まれたNumberが、電話をかける先の番号を指定する部分で『Number名詞』と呼びます。このように、TwiMLの動詞には中に名詞を含められる(ネストできる)ものがあります。

TwiMLの動作を試す方法

TwiMLの動詞の動作を試すには、以下の方法があります。

Webサーバーをお持ちの方

TwiMLをインターネットからURLでアクセスできるWebサーバーをお持ちの場合は、作ったTwiMLをUTF-8で保存し、参照できる場所へアップロードしてURLを控えてください。

Webサーバーをお持ちでない方

Webサーバーをお持ちでない方は、TwilioにあるTwiML Binsをご利用ください。TwiML Binsは無料で静的TwiMLを配置・利用できる機能です。

自動音声応答を作ってみる

始めに、TwiML Binsを利用したProgrammable Voiceの使い方についてご紹介いたします。

1.TwiML Binsの画面を開く

TwiML Binsは管理画面のメニューから遷移できます。まずは左メニューのドットアイコンをクリックしてください。

 

展開したメニューをスクロールし、TwiML Binsをクリックします。

2.新規TwiML Binを作成

+マークをクリックして、TwiML Binを新規に作成します。

3.TwiML Binの設定

一覧画面で見た際にすぐ判別できるよう、FRIENDLY NAMEにはわかりやすい名前を付けてください。それができたら、TwiMLの枠にTwiMLを記述していきます。

処理可能で有効なTwiMLになると、「Valid Voice TwiML」という表示に変わります。Valid になったことを確認して、画面下部の Createボタンをクリックしてください。

ここでは先ほど紹介したSay動詞の例をコピー&ペーストして保存します。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Say language="ja-JP">お電話ありがとうございます。本日は営業を終了しています。またのお電話お待ちしております。</Say>
</Response>

※書式が間違っていると、枠の下部に「Invalid TwiML」という警告が出ます。警告が出ている場合は下記項目をご確認ください。

  • 命令やダブルコーテーションが全角になっていませんか?
  • 命令部は<Response>で始まり</Response>で終わっていますか?
  • スペルミスをしていませんか?

保存が完了すると、SIDにこのTwiML Binの識別子が発行されます。SIDはAPI経由でこのTwiML Binを呼び出す際に必要なものです。

URL欄には、このTwiML Binを入力するためのURLが記載されています。URLの隣にある四角形が連なるボタンを押すか、枠内のURLを手動コピーして、お使いのブラウザの別タブで開いてみてください。

Not Authorized - only signed requests from Twilio are allowed.

すると、このようなエラーが表示されるはずです。

TwiML Binはご利用のアカウント以外が勝手にアクセスできないよう制御されています。API経由で入力する場合は、APIの命令書式にアカウントを認証する仕組みが含まれています。

4.電話番号にTwiML Binを設定

実際に作ったTwiML Binを電話番号に設定してみます。

左メニューの#マークから取得した電話番号のリンクをクリックし、電話番号設定画面を開きます。着信時の設定メニューは下の方にあるため、画面をスクロールします。

画面が開いたら、以下内容で設定し、Saveをクリックします。

設定項目 設定値

ACCEPT INCOMING

Voice Calls

CONFIGURE WITH

Webhooks,TwiML Bins,Functions,Studio,or Proxy

A CALL COMES IN

TwiML Bin
作成した、TwiML Bin

※Twilioでは「外部→Twilio」方向にかかってくるコールを「Inbound」「Incoming」と呼び、「Twilio→外部」方向へかけるコールを「Outbound」「Outgoing」と呼びます。

なおSaveを押すまで電話番号の設定は反映されません。ご注意ください。

5.自動音声応答を確認する

Saveをクリックしたら、この電話番号に実際に電話をかけてみてください。

合成音声が「お電話ありがとうございます。本日は営業を終了しています。またのお電話お待ちしております。」と話したのち、電話が切れたら成功です。

6.電話転送を試してみる

自動音声応答で話したのち、電話を転送して2者通話を試してみます。

先ほどご紹介した手順1~2の要領で、TwiML Binsのメニューへ移動し、以下のTwiML Binを新規作成してください。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Say language="ja-JP">このお電話を転送します。しばらくお待ち下さい。</Say>
 <Dial callerId="+815031XXXXXX">+819035XXXXXX</Dial>
</Response>

※電話番号は実際のものをご利用ください。

Dial動詞のcallerId属性には、ご自身のTwilioアカウントが保有している電話番号を指定できます。発信先の相手にはこの番号が通知されます。

ちなみに相手に通知できる電話番号は、ご自身のTwilioアカウントが取得している電話番号のみとなります。これは日本国内の電話規制によるもので、電話番号詐称を防ぐための仕様です。

※callerId属性に取得していない電話番号を指定してもエラーにはなりません。ただし相手の電話機には『非通知』として着信します。

TwiML Binを作成したら、画面下部のCreateボタンを忘れずにクリックしてください。作成されると以下のようにSIDとURLが付与されます。

TwiML Binの作成が完了したら、手順4の電話番号設定メニューに戻り、着信時のTwiMLを作成したTwiML Binに変更してSaveボタンをクリックしてください。

ここまでできたら、いよいよ動作の確認をしてみましょう。発信者と転送先それぞれの電話機を用意し、発信者からTwilioの電話番号に電話をかけてみてください。「このお電話を転送します。しばらくお待ち下さい。」というアナウンスが流れたのち、呼び出し音が鳴り、Dial動詞に挟まれた電話番号の電話機が鳴れば成功です。

ちなみに発信者番号は、先ほどDial動詞のcallerId属性に指定したTwilioの電話番号が通知されているはずです。

このように、Webサーバーをお持ちでない方でも、簡単な処理であれば TwiML Binsを使ってサーバーレス環境でTwilioを利用できます。ただし複雑な処理を行う場合は、PHPやJavaといった一般的なプログラム言語を使って、動的にTwiMLを生成するプログラムを実装する必要があります。

自動音声応答でユーザーからの入力を受け付ける

自動音声応答を利用する際には、一方的に音声を流すだけでなく、ユーザーからの入力を受け取りたいというニーズも生じるのではないでしょうか。

たとえば宅配便の再配達依頼。お客様が不在通知に記載された電話番号に電話をかけ、問い合わせの種類や希望の再配達日時を電話機のプッシュボタンで入力することで、再配達の予約が完了する……といったシステムを実現したいケースなどです。

このように、音声ガイダンスに沿った操作で処理が進むシステムを『IVR (Interactive Voice Response)システム』と呼びます。今回はこのIVRシステムをTwilioで作ってみましょう。

音声を流して、入力を受け付ける

本記事では、以下の動作をするIVRシステムを作成します。

動作内容

ユーザーがTwilio番号に電話をかけると、問い合わせの種類に応じてボタンを押すよう音声ガイダンスが流れる。

1を押すとAの内容、2を押すとBの内容、3を押すとCの内容が流れ、9を押すとお礼の言葉が流れたのち通話が終了する。

押されたボタンを認識する機能は、TwiMLのGATHER動詞で実現します。これはプッシュ操作をした際に出る、世界共通の音であるDTMF(別名:トーン信号、プッシュ信号)を検知するものです。

GATHER動詞が使われている部分でプッシュ操作が行われると、Twilioは何のボタンが押されたかを検知し、その数字情報を載せて指定されたURLを実行する動作をします。

※GATHER動詞に関するTwilio Docsはこちら

GATHER動詞を利用する際は、以下のようなTwiMLを書きます。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Gather timeout="10" numDigits="1">
  <Say language="ja-JP">こんにちは。東京の天気は1を、神奈川の天気は2を、千葉の天気は3を、終了は9を押してください。</Say>
</Gather>
</Response>

このTwiMLをA CALL COMES INに設定すると、電話をかけた際に「こんにちは。東京の天気は1を、神奈川の天気は2を、千葉の天気は3を、終了は9を押してください。」という音声が流れます。そのまま何もしないと10秒間の無音が続いて電話が切れます。

GATHER動詞の属性であるtimeout="10"は相手のプッシュ操作を10秒待つ、numDigit="1" は相手からプッシュ操作を1桁待つ、というものです。

ユーザーからの入力をサーバーへ渡す方法

GATHER動詞はプッシュ操作が行われた場合、設定されているURLにプッシュ操作で押されたボタンの情報を付帯して実行します。
※URLの設定がない場合、GATHER動画を返却したURLと同じURLを実行します。

上の例のTwiMLが実行された通話において、たとえば1が押されたときには次のようなURLが実行されます。

https://xxxxxxxxxxxxx/xxxxxx?Digits=1

xxxxの部分はご自身でGATHER動詞に設定したURLですが、これを省略すると、このTwiMLが呼ばれたURLに変換されます。? 以降のDigits=1は『URLパラメータ』と呼びます。『URLパラメータ』は、サーバーへ情報を受け渡す手法の一つです。

URLパラメータを受け取るアプリケーションを作る

GATHER動詞を利用した場合、ユーザーからの入力を受け取るには、URLパラメータを受け取る機能が必要です。TwiML Binsは静的なTwiMLしか配置できないため、パラメータを受け取るには、URLパラメータを受け取って処理できるアプリケーションが必要となります。

このGATHER動詞の例を、実際に動くように作り変えてみましょう。

1.TwiMLにaction属性を追加する

GATHER動詞が「押された数字をどのURLへ渡せばいいのか」を指定できるよう、action属性を加えます。

ここでは「https://example.com/test.php」というPHPのプログラムを作成し、このURLでアクセスできる領域に公開している前提です。ここでは、これを『AのTwiML』と呼びます。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Gather timeout="10" numDigits="1" action="https://example.com/test.php">
  <Say language="ja-JP">こんにちは。東京の天気は1を、神奈川の天気は2を、千葉の天気は3を、終了は9を押してください。</Say>
 </Gather>
</Response>

これで、プッシュ操作が行われた際、例えば 2 の数字を押すと、Twilio は https://example.com/test.php?Digits=2 というURLを叩くようになりす。

2.リクエストを受け取るPHPアプリケーションの作成

URLが実行されたあとの処理についてご説明いたします。

ご自身のサーバーにPHP環境を構築し、Twilio PHP Helper Library をインストールしてください。以下のPHPコードを書いてtest.phpとして保存し、URLでアクセスできる領域にアップロードしてください。

ここでは、これを『BのPHP』と呼びます。

<?php
require_once './vendor/autoload.php';
use Twilio\TwiML\VoiceResponse;

$response = new VoiceResponse();

if (isset($_REQUEST['Digits'])){
  $input = $_REQUEST['Digits'];
   switch ($input) {
     case 1:
        $response->say('東京の天気は晴れ、降水確率0%です。', ['language' => 'ja-JP']);
        break;
     case 2:
        $response->say('神奈川の天気は晴れ、夕方にわか雨が降るでしょう。', ['language' => 'ja-JP']);
        break;
     case 3:
        $response->say('千葉の天気は暴風雨、外出はお勧めしません。', ['language' => 'ja-JP']);
        break;
     case 9:
        $response->say('さようなら。', ['language' => 'ja-JP']);
        break;
   }
}
echo $response;

では、このTwilio番号に電話をかけてみましょう。

Twilioに電話がかかってきたとき、最初にTwilioは「AのTwiMLを実行する」動作をします。GATHER動詞でプッシュ操作を待ちつつ、SAY動詞のセリフを読み上げます。

相手からプッシュ操作があると、何の数字が押されたかを認識し、https://example.com/test.php?Digits=1のように、Digits=に入力された数字を当てはめて、action属性のURLを実行します。

このURLが実行されると、BのPHPが処理を開始します。先頭でTwilio Helper Libraryを読み込み、最初のif文で『もしこのPHPが呼ばれた際に、Digitsという名前のパラメータが定義されていれば、=から右の数字を $inputという数字に代入する』という動作をします。

そしてこの$inputの内容に応じて、switch文による条件分岐が行われます。プッシュされたのが1であれば、このライブラリの力を借りて以下のようなTwiMLをechoし、Twilioへ渡すプログラムです。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Say language="ja-JP">東京の天気は晴れ、降水確率0%です。</Say>
</Response>

このTwiMLを受け取ると、電話からは「東京の天気は晴れ、降水確率0%です。」という音声が流れてこのTwiMLが終了します。TwiMLが終わると制御はTwilioへ戻り、AのTwiMLの続きを処理する形になります。

もう一度、AのTwiMLを振り返ってみましょう。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Gather timeout="10" numDigits="1" action="https://example.com/test.php">
  <Say language="ja-JP">こんにちは。東京の天気は1を、神奈川の天気は2を、千葉の天気は3を、終了は9を押してください。</Say>
 </Gather>
</Response>

GATHER動詞がtest.phpへ値を渡し、その処理が戻ってきてGATHER動詞の処理部分が終わりました。続く動詞はありません。よってAのTwiMLも終了し、電話が切断される、という流れになります。

ここでさらに何か案内を流したい場合は、GATHER動詞の後ろにまた別の動詞を置いて、AのTwiMLに戻ってきたあとで処理するように設定すればOKです。

これを応用することで、action属性のURLを跨いで複雑な応答フローや条件分岐をプログラムできます。Twilioを使うことで、既存のIVRシステムでは実現できないフローを組むことも可能。つまり、ご自身のお好みでフルカスタマイズのコールセンターを構築できるのです。 

通話の保留

TwiMLを利用すると、自動音声応答のほかにも、電話の転送機能や音声録音といったさまざまな機能をご自身で実装することが可能です。

たとえば「パーク保留機能」。外線を受けた際にあらかじめ設定してあるパーク保留ボタンを押すと、どの電話機であっても同じ数字のパーク保留ボタンを押して電話に出られるようになる機能です。

代表電話にかかってきた外線を簡単に担当者へ取り次げることから、オフィスの電話ではよく使われています。

このような仕組みも、Twilioでプログラムできます。

コールレグ

Twilioを使って保留機能を実装する前に、『コールレグ』という考え方についてご紹介いたします。


 

左の電話機AがTwilio番号Bに電話をすると、TwiMLのDial動詞によって右の電話機Cに電話がかかり、電話機Aと電話機Cが繋がります。このとき最初にかけてきたA側のコールを『親コール』、TwiMLで発信されたC側のコールを『子コール』と呼びます。

ご自宅の電話機から別の電話機に電話をかける場合、相手の電話番号を直接ダイヤルするため、AとCは電話網の中で1本の回線に繋がっています。しかしTwilioでは「かかってきたコール」と「かかってきたコールで実行された、TwiMLがかけた新しいコール」は別物として扱われるのです。

このように、2人の相手間で接続されているコール1本1本をコールレグと呼びます。単に「コール」というときは漠然と通話を指すイメージですが、「コールレグ」は発信行為・着信行為を意識しつつ、そのコールの接続像全体を意識して指すイメージです。

Twilioではプログラムでコールを操作するため、「どのプログラムやTwiMLがどのコールを生成したのか」という点を強く意識します。このため、コールレグという呼び方をすることが多いのです。

つまり上記の図においては「着信した親コール」「新たに発信された子コール」の2本のコールレグが生成され、これらのコールレグが互いにTwilio内で音声トンネルを介して繋がっているということになります。

コールレグを意識した保留機能

  • 左の電話機AからTwilio番号Bに電話をかけると、右の電話機Cへ転送され、AとCが音声通話を実現する。
  • 通話の途中から、電話機Aと電話機Dに繋げ直したい。

という状況があったとしましょう。このときコールレグの概念を意識すると、以下の図のように表すことができます。

黄色の両端矢印は、誰と誰が音声で繋がっているかを表します。

①電話機AがTwilio番号050-Bに電話をかける

最初にAがTwilio番号050-Bに電話をかけます。

このとき050-Bに設定しているA CALL COMES INで、TwiML Binまたはご自身で用意したTwiMLまでのURLが実行され、Cへ電話をかけるための Dial動詞が含まれた命令が実行されます。

この時点ですでに2本のコールレグが生成されています。

  • A → 050-B : Twilioへの着信コールレグ   (親コール)
  • 050-B → C : Twilioからの発信コールレグ (子コール)

大切なのは、この2つのコールには親子関係があるということです。Aからの着信をもってTwiMLが呼ばれ、Cへのコールレグが発生しているため、最初の着信が親コール・次の発信が子コールという関係になります。

このときTwilioの仕様として、親コールを切ると子コールも連動して切れます。こうしないとAが電話を切っても、TwilioとCが相手不在のままコールを継続してしまうからです。

この時点では、AとCがお互い音声で話していることになります。

②電話機Aを一旦保留にする

次に電話機Aと電話機Dを繋げていきます。ここでまず行うのが、「Aを一旦保留にする」ことです。

ENQUEUE動詞を使うと、該当コールの相手をキューにできます。Twilioでは自分の好きな名前でキューを作成可能で、この図では「N」という名前のキューを作っています。

またTwilioでは接続中のコールをAPIリクエストを使って更新(Update)できます。この図では「Aからの着信TwiML」でTwilioからCへの発信コールレグを生成しましたが、このコールレグに対してAPIリクエストを使って別のTwiMLで命令を出すことで、Updateが可能となります。

では、AをキューNに入れるためにAPIリクエストでENQUEUE動詞を含んだ命令を出しましょう。この時点で Aの相手はキューNになり、Aのコールは保留されます。

そしてAがキューNに接続されると同時に、Cとの通話は切れることになります。親コールレグがUpdateされたことで子コールが無効となり、Cのコールレグが切断される……というわけです。

コールレグを意識した保留解除

次に、Aの保留を解除してAとDを音声通話で繋げます。

Twilioは「キューに電話をかけるとキューの中にいる人と繋がる」仕様になっています。現在キューNにはAのコールレグがいるため、APIリクエストを使って新規発信コールレグを作りましょう。

まずDial動詞を使って、TwilioからDの電話番号へ発信(新規子コールレグ2)します。続いて別のTwiMLで「Dが電話に出たら、TwilioからキューNに発信する(新規コールレグ3)」命令を作ります。この子コールレグ2・3 はワンセットです。2つの発信コールレグはTwilio内で音声トンネルによって繋がれています。

これでDはキューNに接続されました。Twilioではキューの中にいる相手と繋がった時点でお互いがキューから出て、Twilioを挟んだ2本のコールレグになるため、DはキューNに接続されると同時にAと繋がることになります。

AとDが結ばれたコールレグへ変化すると同時に、AもDもキューNから出ます。その時点でキューの中には誰もいなくなるため、キューNは消失します。

通話の切断

最後に、通話の切断についてもご紹介いたします。

上記図ではAが先に受話器を置く、つまり親コールレグから切れることを想定しています。親コールレグが切れるため、子コールレグであるTwilioとDのコールレグも瞬間的に切れます。

では、Aより先にDが電話を切った場合はどうなるでしょうか?

TwilioとDは子コールレグです。子が先に切った場合、Twilioは「Dとの通話を実現するTwiMLが終了したため、続きのTwiMLを処理する段階」に移ります。

しかし本来あった「AがTwilio番号にかけるとCに繋がる」親コールTwiMLは、Aを保留するためにUpdateされ、無効となっています。よって続きの処理が存在しない状態になり、親コールレグを終了することとなります。

コールレグの概念を保留以外に応用する

コールレグの考え方を理解していると、保留機能を実装する以外にもさまざまな形で応用できるようになります。

以下のようなコールフローを考えてみましょう。

このコールフローはTwiML単体で済む、TwiML Bins だけを使って実現できるコールフローです。以下のような TwiML で実現できます。

<?xml version="1.0" encoding="UTF-8"?>
<Response>
 <Dial callerId="+8150B">+8190C</Dial>
 <Say>Have a nice day</Say>
</Response>

図を見ながら処理の流れを確認してみましょう。

上記のTwiMLがTwiML Binとして作成され、Twilio番号 +8150BのA CALL COMES INの設定に指定されているものとします。

左の電話機AがTwilio番号Bに電話をかけると作成したTwiML Binが実行され、まずDial動詞の通り090-Cに発信します。Cが電話に出るとAとCの音声通話が開始されます。このときA→Twilioの着信コールが親コールレグ、TwiMLで生成されたTwilio→Cの発信コールが子コールレグです。

ここでもしCから電話を切ったとすると、子コールレグが終了しただけで、親コールレグはまだ継続している状態になります。つまり前述のTwiMLのうち「Dial動詞の命令が終わった」だけです。そのあとにあるSAY動詞はまだ残っているため、Twilioは命令通り「Have a nice day」と発声します。そのうえでTwilioから電話切って通話が終わる、という流れです。

まとめ

Programmable Voiceの基本はこれですべてですが、Twilioにはこの記事で紹介しきれなかったTwiML動詞やAPIがまだまだたくさんあります。

どのようなものがあるのかチェックして、ぜひ活用していただけたら幸いです。きっとご自身にぴったりなコールフローを作成することができますよ!

※Programmable VoiceについてのTwilio Docsは以下のURLから参照できます。

* Programmable Voice 全体のトップページ

* Programmable Voice で使う TwiML

Twilio 本部
Twilio 本部

KDDIウェブコミュニケーションズは、日本初のTwilioパートナーとして常に「開発者目線」を大切にしており、ブログ記事がお役に立てれば幸いでございます。

Share!!

  • お役立ち情報
  • イベント情報
  • 相談会申込
  • 導入事例