Article

ブログ

2015/10/21

Twilio で保留機能を実現 詳細 ver

こんにちは、本間です。

本日はクラウド電話 API である Twilio の保留機能にフォーカスを当てて解説します。

弊社では クラウド電話CTIサービスの CallConnect の他にも、 Twilio を用いた開発を受け付けております。

さて、保留機能に関しては、既に以下の Twilioブログに実装方法が記載されております。

Twilioを使って保留機能を実装。

実際に CallConnect で保留機能を提供する上で、他に注意すべき点をまとめてみます。Twilio の上級者向けトピックです。

用語の確認と前提知識

  • “発信者”はTwilioの050番号にかけてきたお客様を表します。
  • “オペレータ”はClientで受信する側を表します。
  • Clientを利用できる環境にあるとします。
  • TwiMLREST API など基本を理解しているものとします。

保留させるには、通話のアップデートを用いる

Twilio には、通話をアップデートする、という熱い REST API が提供されています。これを用いて、現在通話中の電話を、Queueに待たせる部屋に飛ばすことができます。これが基本的な保留の仕組みです。

通話をアップデートするには、CallSid という通話に紐付いているIDを取得する必要があります。

そこで、先ほどの Twilio 公式ブログを読んでみてください。”CAxxxxxxxxxyyyyyyyyyy” という CallSid の取得は、わかりやすくするために 通話自体を REST から作成するサンプルでした。確かにこれだと Sidを取得できます。しかし、通常は保留したいのはオペレータ側のはずです。電話がかかってきてClient上で通話しているときに、どのようにしてこのSidを取得すれば良いのでしょうか。

Clientで電話がかかってくると、 Connection オブジェクトの parameters の中に CallSid を取得することができます。これを Ajax なりなんなりで送ることで、CallSidは取得できます。

ただ、そのCallSidをアップデートして Enqueue しても意味がありません。オペレータ側の通話がアップデートされて、発信者側の通話が切れる、という事態に陥ります。

なぜこうなるのかというと、 Client で取得した CallSid は、TwilioとClientとの通話のSidであり、発信者とTwilioとの通話のSidではない という点です。わかりにくいですね。

Twilio には、 ParentCallSid という概念があります。その名の通り、通話には親子関係が存在し、発信者からTwilioにかけた通話が Parent, Twilioからオペレータにかかってきた通話が Child となります。

そこで、Ajaxで送ったCallSidからCallを取得し、そこにあるParentCallSidを取得し、再びそのParentCallSidを用いて親のCallを取得します。そのCallをアップデートすることで、発信者側の通話をアップデートし、Enqueueによって音楽を流すことが可能となります。

保留には Conference ではなく Queue を用いる

まず、保留の方法には Twilio では2つ方法があります。一つはTwilioブログにあるように Queue を用いる方法、もう一つは Conference を用いる方法です。

私はこのどちらも試しましたが、 Conference を利用した場合、受付側は複数回の保留・再開を受け付けるとした際、endConferenceOnExitを指定できません。なぜならば2回目の保留を始めた時点で通話が終了してしまうためです。この制約のため、会話が終了して、オペレータ側が切断したとしても、発信者側は自ら会話を切断しない限り会話が永遠に続いてしまうことになります。この問題があるため Queue を利用します。

保留している間は、オペレータ側は通話を切断しなければならない

これも結構はまりました。Twilio のクライアントを利用していると、できれば通話を切断せずに保留を続けることで、 disconnect() が呼ばれないようにしたいと思うものです(実装すればきっとそう思うはず!)。

これを実現するために、オペレータ側は 通話のアップデートを用いて TwiML の Pause を使って待たせるような実装をし、反対に発信者側は 通話のアップデートを用いて Enqueue する TwiML を返すようにしてみました。そして再開するときに 通話のアップデートで Dial Queueすれば、通話を切断せずに保留が実現できる!そう信じていました。しかし、実際にやってみると音が途切れて聞こえます。通話がごちゃごちゃになってしまって、これでは使い物になりません。

このような謎の問題が発生するので、保留するときは オペレータ側は Pause などを使わず、素直に通話を切断しましょう。 発信者側の 通話のアップデートで Enqueue すれば、勝手にオペレータ側の通話は切断されます。

通話がdisconnect されてしまいますが、保留を押してdisconnectが呼ばれた場合は、再開のボタンを表示し、作成したQueueの部屋に Dial Queue するような発信するときのTwiMLをTwiMLAppから定義します。ここら辺はClientの通常の電話番号の発信方法とあまり変わりません。

これは同時に録音ファイルが複数できてしまうことを意味します。保留・再開を繰り返した上でさらに通話の全てを録音したい場合は、 最初の Client にかけるTwiML の record="true" 以外にも、 オペレータ側から再開する TwiML, Dial の action にも、同様に record="true" を付与して複数録音URLを受け付けるようにする必要があります。通話が切断されてしまうため、複数録音ファイルができてしまうのです。

まとめ

今回は Twilioの上級者向けトピックを扱いました。

Twilio はカンタン!というのは確かに最初はすごい感動しますが、突き詰めればこういう複雑な部分もあります。

こうした開発が大変だと感じられた方は、 宣伝となりますが、 CallConnect のご利用を検討してみてはいかがでしょうか。 保留機能をはじめとした Twilio のあらゆる機能を実装して提供しております。