TaskRouterを日本国内で使う場合の注意点

こんにちは、@24guchiaです。

日本国内でTaskRouterを受電で使う場合、通話音声が遅れる可能性があります。今まで、TaskRouterを使いましょうみたいなことを書いていたので、
その反省と皆様への注意を兼ねて記事にします。

原因

受電が遅れるということですが、原因はTaskRouter自体の仕組みにあります。TaskRouterはTask割り振りをして、米国サーバーでキューが作成されます。
そのままdequeueをすると、
米国サーバーで作成されたキューを介して通話が始まります。
そのため、日本国内のピア同士の通話であっても
米国サーバーを経由することになるため、
音声の遅れが発生します。

対応方法

dequeueを使うのではなくConferenceを使いましょう
Conferenceの作成方法はドキュメント見てもらおうとして、
Conference作成時、リージョンの指定ができます。
このリージョンをjp1に設定することによって、日本国内での通話が実現できます。

まとめ

1月にリニューアルしてから、通話が遅れることがあるとよく言われていました。
アルファー版で発生していなかったので、なんでだろうと悩んでいましたが、
原因がわかればなんということはないです(遠い目)。

現在、 通常のCallからConferenceに置き換える作業しています。
これはなかなかに骨が折れますので、
これから日本国内で導入を考えているTwilioデベロッパーの皆様、
予めConferenceでの実装をお勧めします。

Conferenceへの置き換え苦労話は今度、まとめます。
とりあえず言えることは、単純な置換では絶対に動かないし、
1対1が前提の通話に対し、複数人が通話する前提のConferenceでは
そもそも考え方が異なります。
この辺はかなり苦労しています。

Twilioのアカウント周りで失敗したのを懺悔

あけましたおめでとうございます、@24guchiaです。

年始から縁起悪い記事ですが、今日失敗したことまとめます。

ほうほうの人に質問してしまっていて、申し訳ない気持ちでこの記事書きました。

この記事を読むと分かること

Twilio.Clientを用いて、何故か架電ができず、

下記ログが出力される時の原因と解決方法が分かる

[Connection] Received HANGUP from gateway

書いた理由

  • ググっても出てこなかった
  • 同じミスを自分がしないようにメモ
  • 後から始めたTwilio開発者が同じミスでハマらないようにしたい

今日の僕のハマってた時間と、ほうほうの人に質問で時間取らせた分、

他の人がこの記事ですぐ解決できれば開発者全体でプラスにしたいため。

事象

なぜか架電できない

同じ実行環境で架電すると、なぜか架電ができる番号とできない番号がある。

※実行環境は原因に関係ないので、特にあげません。

正確には架電すると架電の呼び出し音は一瞬鳴るが、

架電先の電話機が鳴動する前に架電が終了する。

切り分けてみた

  • 架電先の電話機固有の問題

携帯電話にかけても、固定電話にかけても架電ができなかったので、

架電先電話機は関係ない。

  • 実行環境の問題

同じ環境で別の番号を用いた場合、架電が出来たので実行環境は関係ない。

  • ネットワークの問題

無線LANと有線LANを切り替えても、かからなかったのでネットワークは関係ない。

  • ソースコードの問題

プロダクション版とアルファ版で同じ番号でかけたところ、

アルファ版ではかかるのでソースコードに問題ありそう。

コンソールのログ読んだ

ICEコネクション周りは正常に終了していた。

※ICEってなんだ?って人はこの記事参照してください

架電先に届く前に先に上げたログが出力されていた。

[Connection] Received HANGUP from gateway

 

このログはIP網とPSTNをつなぐゲートウェイから、

電話切られたっていう信号を受信したというログです。

なので、通常に通話し、相手側に切電ボタン押されたり、

受話器を置いた時に送られる信号です。

ゲートウェイについて参考:https://www.3cx.jp/voip-sip/voip-gateway/

考えた

相手先に届く前にゲートウェイから、通話終了の信号が来るのは

ネットワークとかに問題があると思ったがぜんぜん違っていた。

原因

Twilioにはマスターアカウントとサブアカウントがあって、

画面に表示している電話番号と生成する認証トークンが不一致だったのが原因。

マスターアカウントの認証トークンを基に生成されたDeviceで、

サブアカウントの番号を使用して架電しようとしていたので、

架電ができませんでした。

ハマった理由

ICEは正常終了しているのに関わらず、

即時でゲートウェイからハングアップの信号受信したログが出たから。

IPとPSTNの間にあるゲートウェイ周りの情報も

逆に存在を知らなければ、変にハマらなかったかもしれない。

まとめ

認証トークンはドキュメント通りに作れば、正常に返ってきます。

電話番号はTwilioで買えば、買ったアカウントに紐付きます。

認証トークンと電話番号、本当に紐付いているか再度確認しましょう。

プロダクションで使うTaskrouter構成について

この記事を読むと分かること

  • プロダクションで使うTaskrouterガチ構成が見れる
  • WorkflowのルーティングのJSONファイルを公開するので、ドキュメントとは違うユースケースのルーティングを見れる

こんにちは、@24guchiaです。

Twilio Advent Calendar 2017 の13日目です。

Taskrouterと1ヶ月ほど格闘し、得られた情報を社外秘のみ取り除いて、全部公開します。

Twilioドキュメント以外で、Taskrouterの記事が少なくいろいろと苦戦したので、

今後Taskrouter使う人の参考になれば良いなーと思います。

弊社の受電の仕様

受電の仕様は下記です。

  • 受電した番号でDB検索し、担当者が存在するか確認する
  • 担当者が存在する場合、担当者の電話機を鳴らす
  • 担当者が電話を取らないか不在の場合、担当者と同じ部署の人の電話機をランダムで鳴らす
  • 誰も受電出来ない場合、機械音声で担当できるものがいない旨を通知

企業側としては受電担当部門が不要になり、

お客様としては余計な取次による待ち時間が減らせることができます。

CTIの効果を感じられる仕組みだと思います。

Taskrouterに落とし込むとどうなるか

Workerの設定

Workerは電話機を使う人、一人に対して1Workerを必ず発行します。

独自で持たせている属性はメールアドレスと部署IDだけです。

FriendlyNameはemailからピリオドをアンダースコアにしただけのものを使用しています。

例:

{"email":"hiroshi.abe@example.com,"contact_uri":"client:hiroshi_abe","department_id":1}

Activityの設定

デフォルトで生成されるものをそのまま使っています。

Taskqueueの設定

TARGET WORKER EXPRESSIONに1==1を入れているだけの

キューをひとつだけ使用しています。Workflowだけでなんとかしています。

Workflowの設定

設定しているJSONファイルは下記。

これだけだと、何も出来ないので好きに使ってください。

WorkflowのJSONの解説

パッと見、filterって何してるんだろうと感じると思います。

これを説明するためにまず、Taskqueueの仕様について理解が必要です。

Taskqueueの仕様

Taskqueueはキュー内に存在する、WorkerのAvailabilityはチェックしません。

そのため、割り振りしたけど、そのWorkerが離席してて受電できなかったというようなことが発生しました。

こうやって回避した

離席している人の電話機を鳴らすということを回避するために、

Task発行前に担当するWorkerのAvailabilityをチェックするように変更しました。

Availabilityがtrueの場合、taskにキーがfilter、値がemailの属性を設定します。

falseの場合、taskにキーがfilter、値がdepartment_idの属性を設定します。

この属性はfilter_friendly_nameがemaildepartment_idの下にあるexpressionで評価される際に使用します。

filterがemailの場合

targetsの中に2つのキューだけあります。

taskにemailの属性が設定されてあり、担当者のメールアドレスが情報として持たせてあります。

この属性を設定することにより、Taskqueueの中からWorkerのemailの属性が合致するものが選択されるため、

まず担当者の電話機が直通で鳴るようになります。

timeoutを10秒にしてあり、在席しているが取ることができなかった場合でも、

自動で次のQueueにエスカレートされ、次の判定であるdepartment_idが一致するWorkerの電話機を鳴らすようにしてあります。

担当者に直通で電話機を鳴らす場合の具体例:{"person_name":"Alice","email":"hiroshi.abe@example.com","department_id":1,"filter":"email"}

filterがdepartment_idの場合

targetsの中に1つだけキューがあります。

先の例と同様ですが、email情報は持っていません。

そのため、Taskqueueの中からWorkerのdepartmnet_idの属性が合致するWorkerが選択され、

担当者と同じ部署の誰かの電話機が鳴らすようにしています。

こちらはtimeoutを設定していないため、電話を切られるまでか、

同じ部署内の誰かが電話を取るまで鳴り続けます。

担当者と同じ事業部の誰かの電話機を鳴らす具体例:{"person_name":"Bob","department_id":1,"filter":"department_id"}

回避した結果

この仕組で不在の担当者に一度着信させて、お客様を待たせるということをなくすことができました。

まとめ

Twilioを利用するメリットはいくつもありますが、

受電から担当者への取次時間を減らせるということは

Twilioを導入する企業、架電するお客様の双方に大きなメリットがあります。

  • 直通で担当者につながることにより
    • お客様への安心感の提供
    • 取次が減らせるため、オペレーターが電話業務に取り掛かる時間が減る
    • 通話時間が減るので金銭的に通話料を節約できる

このようなメリットを感じられたら、ぜひTaskrouterの導入をおすすめします。

受電の難しさとどう解決したかについて

この記事の主張

  • Twilioを用いたWebCTI構築で一番難しいのは受電である
  • 保留も難しいと言われるが、保留の実装はドキュメントだけで解決する
  • 手を動かす前に、仕様洗い出しと実装のイメージ作りをしましょう

 

こんにちは、@24guchiaです。

Twilio Advent Calendar 2017 の9日目です。

弊社では営業管理ツールリニューアルに伴い、

電話システムも某IP電話会社から、Twilioへの置き換えを行い、新たにCTIの仕組みを導入しています。

導入にあたり、仕様の洗い出しや提案、実装から各社間の調整まで仕事させてもらっています。

僕はTwilioに触る前まで、IP電話のサービスを使ってなかったし、Twilioは名前も知りませんでした。

1年ほどで得た経験を基に受電の難しさをまとめますので、参考にしてください。

この記事に書いてある内容はTwilioに詳しい人に質問できる環境にありながらも、

基本的には1人で得た知識と経験のため、これがベストプラクティスではないです。

むしろそんなのあったら教えて欲しい。

なぜ受電が難しいのか

IP電話やTwilioについて詳しくない人が、

そもそもネットワークを用いた電話の仕組みを理解できていないからです。

携帯電話はほとんどの人が持っていますが、仕組みが異なります。

電話番号1つに対して、通話を発信・着信できる端末が複数ある

普通の電話は番号1つに対して、発信・着信できる端末は1つだけです。

ですが、Twilioでは1つの電話番号で、複数人が同時に発信・着信できます。

一般的に思い込んでいる、電話番号と端末が1対1なのに対し、Twilioは一対多の関係にあります。

もちろん、1対1の作りでも構築できますが、月額108円が最低でも1人ずつにかかり、

管理コストも膨大なことになります。

これはTwilioが提供しているJavaScriptライブラリや、iOS/AndroidのSDKを使用し、

ブラウザなりアプリなりで仮想電話端末を実装することで解決します。

言われれば当然ですが、いざやってみないと身にしみて分からないこともあります。

同じ電話番号にかかってきた通話を誰に割り振るかを考えないといけない

先のことを理解した時に、この問題にぶつかります。

Twilioへ指示を出すことで誰に割り振るかの指示は出せますが、

誰に割り振るか自体は自分たちで考える必要があります。

この時点で、システムだけでは解決できず、現場で仕事している

営業やオペレーターなどと連携が必要です。

また、先の事実はエンジニアであればすぐに理解できるかもしれませんが、

必ずしもITリテラシーの高くない人へ納得性のある説明をした上で、

現場でどう割り振るのがベストなのかコミュニケーションを取る必要があります。

新しい技術に触れながら、現場の知識も取り込んでいかないといけない。

リアルタイムとの戦い

仕様も無事に決まりました。次に襲いかかる問題がこれです。

一般的なWebエンジニアであれば、実戦経験の少ない

リアルタイムとの戦いが待っています。

受電した通話を誰に割り振るかは決まっても、

その人が在席していないとその通話は空振りになりお客様を待たせることになります。

そこでかかってきた時点のオペレーターの状態を取得する必要があります。

リアルタイムで状態を取得する方法

下記3つが簡単に思いつきます。

  1. DBなどに管理し、逐一問い合わせてみる
  2. Twilio.Syncを使ってみる
  3. Twilio.Taskrouterを使ってみる
DBで管理する場合

在席状態を管理するために、逐一ajaxなどでその人の状態をupdateし続ける必要があります

これはサバクラ両方を1人でスクラッチしつつ、

保守フェーズですべて管理する必要があります。

人数が少なければ可能かもしれないですが、あまり現実的ではなさそうです。

Twilio.Syncを使う場合

SyncとはTwilioが提供しているWebsocketを用いた、リアルタイム通信ができる機能です。

最初に僕がやってみたのがこれでした。

Syncを使うとサーバ側実装がなく、インフラの設定や保守が不要で、

使用した分だけの料金で使うことが出来ます。

ただこの機能は検索性が高くなく、500件のデータを入れたSyncを検索した所、

10秒ほどかかってしまい、受電で使うには難しかったです。

人数次第では選択肢に入ってくるかもしれませんが、実装した上で弊社では採用しませんでした。

Syncを使おうとした時の記事は下記を参照。

http://harinoma.info/?p=32

Twilio.Taskrouterを使う場合

TaskrouterとはTwilioが提供しているACDです。

ACDとは通話を誰に割り振るか分配する機能です。

ロードバランサーというとイメージが付きやすいと思います。

Taskrouterは受電に特化した機能です。最終的に弊社で採用したのはTaskrouterです。

Taskrouterについては、下記記事参照。

http://harinoma.info/?p=45

Taskrouter実装との戦い

ライブラリは提供されているだけなので、当然実装する必要があります。

実装するにあたり、一番苦戦した点はドキュメントではもっとも単純なケースの例しかなく、

弊社の仕様ではどうTaskrouterを構築し、実装すべきなのかわからなかったことです。

自分のベストを尽くしたつもりだけど、

構築した環境が良いのかどうかは運用フェーズまで明らかにならないと思われます。

デバッグの大変さ

最終的にはPC4台+サブディスプレイ2枚+電話機1台+私用携帯電話1台を用いた

デバッグ構成で実機デバッグをしました。

一般的なTwilioエンジニアの開発風景

受電した通話の情報を元にどのようなタスクが作成され、誰に割り振られるかまでは

実機がなくてもデバッグ可能です。(これもまあまあ大変ですが)

ですが、在席離席の挙動は想定通りか、リアルタイムで在席状態が正しく取得できるか、

クライアントの通話に問題はないか、タイムアウトとエスカレートの挙動の確認など、

実機で試さないとわからないことが多いです。

物理的にデバッグ環境構築が大変なのは初めてでした。

構築した後もなかなか大変なデバッグ作業になります。

すべてを乗り越えて

晴れて受電の機能が完成です。

受電1つ取ってもこれだけの大ボリュームが待っています。

特に失敗したなと感じたのは、Syncの速度感をもっと早く調べておくべきだと思いました。

弊社では、SyncもTaskrouterもどっちも使うよくばりプランなので、

Syncの実装自体は有用でしたが、最速の実装かと言われるとそうではなかったです。

弊社の場合、ACDを導入していなかったため、

とりあえず導入するだけでも改善効果が見込めます。

具体的には担当営業へ直接つながることによるお客様への安心感の提供、

取次時間を減らせることへの業務改善です。

タイムアウトやエスカレートの仕組みは今回あまり活用できていませんが、

今後の改善へ手が打ちやすくなる布石として考えています。

やっぱり難しそうだな〜と思うあなたへのメッセージ

https://twiliomeetup.doorkeeper.jp/events/68355

このイベントに参加しますので、ぜひ話しましょう!

僕だけでなく、Twilio開発に携わるエンジニアがたくさん参加しますので、

得られることもたくさんありますよ。

次回予告

12/13のアドベントカレンダーで具体的なTaskrouterの設定例を載せますのでお楽しみに。

WebRTCについて調べた

WebRTCについて調べた

こんにちは、@24guchiaです。

Webの記事何本かと本2冊買って読んでみたので、一度、現状の理解を書いてみます。

ちなみに買った本は下の本と、

 

わか(った気にな)るWebRTCの電子版です。

https://booth.pm/ja/items/504677

読む順番としては、わか(った気にな)るWebRTCを読んで、

ざっくり概要を頭に入れてわかった気になってから、リックテレコムのWebRTCの本を読むと良いと思います。

いきなりリックテレコムから入ると心が折れること間違い無し。

最近、リックテレコムから販売されている本を買うことが増えてきた。

この記事で分かること

WebRTCってそもそも何か、どういうところで使われてて、

どんなプロトコルが用意されているかが分か(った気にな)るようになります。

なんで調べたの?

Twilioを使うにあたって、Twilioがそのあたり難しい部分を吸収したライブラリやSDKを用意してくれてるけど、

デバッグするにあたってあまりにも分からないことが多すぎたため。

Twilio使わないから知らなくても良いや〜って思わず、ネットワークについての勉強になるし、

最近ではiOS11からWebRTC対応されスマホ全般で使える技術となったので、

Web系の開発をしている人は押さえておくべき技術になっていくでしょう。

WebRTCってそもそも何?

Web Real Time Communicationの略。名前の通り、

ブラウザでのリアルタイム性を持つコミュニケーション全般を取り扱います。

コミュニケーションは具体的に、音声通話や動画(ビデオチャット)などを指します。

特長はインターネット回線につながっているブラウザさえあれば、

上記コミュニケーションを行える点です。

もう電話機や専用のソフトウェアは必要なくなります。

WebRTCを使っているサービスは何がある?

Twilio

appear.in

Slack音声通話

などがあります。使ったことがあるサービスがあると思います。

リアルタイムコミュニケーションってどうやってるの?

  1. 音声などの情報入出力の許可をユーザによって行わせる
    • 不正にユーザの情報を収集しづらくするために、ユーザに許可・拒否を選択させる
  2. ピア同士の接続の確立
    • 次に詳細な説明を書きます
  3. ピア同士のデータ交換
    • データ交換によって、音声通話やビデオチャットが可能になります
  4. 接続の終了

ピア同士の接続の確立って難しそうだね?

はい、難しいですね

接続の確立について、オファーアンサーネゴシエーションという

ローカルとリモートの設定を交換する手法があります。

  1. 接続を試みる側がどのメディアどのデコードで送るかをオファーとして送る
  2. 受け手側は、送られたオファーに対して、対応可能かと他に使いたいものリストをアンサーとしてオファー側に送る
  3. アンサーを受取、各ピア同士で受け取った情報を設定することでデータ交換が行えるようになる

ネットワークの制限

セキュリティを高めるためのファイアウォールや

NATの存在が接続の確立にあたっては障害となる。

その回避を行うため、特別なプロトコルが用意されています。

NAT is 何?

Network Address Translatorの略。

IPアドレスは有限の資源であり、資源の有効活用のために使われる。

グローバルIPをNAT機能持ちルータで、ルータ内のプライベートIPとの変換を行う技術。

NAPTであることがほとんどで、ポートの変換も行うことが多い。

正確にはNAPTだけど、一旦NATで統一します。

ピア同士が接続されるWebRTCだが、

NATの存在のため、接続先ピアがどのプライベートIPを持っているかが

外側からは分からないため、下記NAT越えが行われる。

NAT越え is 何?

上記問題への対応のため、ピアに直接パケットを送るために行われる手法・技術。

具体的には、ホールパンチという手法でNATを透過したテストパケットを送れるかどうかを試す。

ホールパンチ is 何?

NATの外から、プライベートIPアドレスとポート番号のペアを知るために行われる手法。

具体的には下記手法を試していく。

ICE is 何?

Interactive Connectivity Establishmentの略。プロトコルのひとつ。

NAT越えを行うための手法の一つ。ICEでは下記を行う。

  • IPアドレスとポート番号のペアを集める
  • ピア同士がペアを交換する
  • ホールパンチを試す
  • 繋がるペアでデータ交換を行う

上記が純粋な手法で、よくあるICEではSTUNプロトコルとTURNプロトコルを使い、

ピア同士の接続の確立を試みます。

また、VanillaとTrickleという拡張がある。

Vanilla ICE is 何?

標準のICEを指す。拡張であるTrickleが出来たため、標準がVanillaと呼ばれる。

VanillaはすべてのIPアドレスとポート番号のペアを収集してから

すべて接続を試し、接続確立されたものから使用するペアを選択する。

バニラという単語自体には標準という意味がある。

ICEという名前のためのシャレみたいなもんでしょうね。

Trickle ICE is 何?

標準のICEに対し、拡張されたICEを指す。

Vanillaに対し、Trickleではペアを順次交換し、接続成功した時点で処理が終了されるので、

接続確立までがVanillaよりも速くできる可能性がある。

現時点ではChrome/Firefoxと一部ブラウザでしか対応していないため、

使用する際には最新の情報を調べてください。

Trickleは滴り落ちるという意味なので、ペアを少しずつ試すという点が

アイスが滴り落ちるのと様子に似ているからこの名前なんだと思います。

STUN is 何?

Session Traversal Utilities for NAT の略。プロトコルのひとつ。

これもNAT越えのための手法のひとつ。

STUNで対象のピアのネットワーク上にNATが存在するかどうかを確認するプロトコル。

テストパケットをSTUNサーバに送り、自分のIPが外部のネットワーク上からどういうIPで見えるかを確認します。

自分のIPと一致していれば、NATは存在しません。

NATが存在しなければ、NAT越えの必要なくパケットを送ることが出来ます。

存在する場合は、NATが一つ以上存在し、一番外側のNATの情報が取得できます。

STUNでアドレスとポートのマッピングを取得します。

このマッピング情報をもとにピア同士で接続するのがSTUNです。

TURN is 何?

Traversal Using Relays around NAT の略。プロトコルのひとつ。

TURNはSTUNの拡張プロトコル。ICEがホールパンチに失敗した場合、メディアリレーを行う。

ブラウザに実装されているTURNクライアントと、NATの外にあるTURNサーバと

接続先のピアがTURNサーバを経由し、メディア情報を交換している。

STUNとの違いはSTUNはピア同士で接続するのに対し、

TURNはピアとピアの間にTURNサーバが存在し、

TURNサーバ経由で接続する点が異なります。

ICEとSTUNとTURNの関係

同じNAT超えをしているし最初どういう関係かわかりませんでしたが、

iwashiさんからTwitterでリプライいただけたので書いておきます。

各プロトコルは独立している。TURNはSTUNの拡張プロトコル。

ICEはICE自身でのアドレスとポートのマッピングを行い、

さらにTURNとSTUNも利用するプロトコルです。

まとまれ

これらのプロトコルを用いて、ピア同士で接続できれば晴れてリアルタイムコミュニケーションが楽しめます。

Twilioではこの辺り難しいところを何も考えずに使える点が良いですね。

音声通話はもちろん、最近ではビデオチャット機能も充実してきているとのことなので、

手っ取り早くWebRTCに触れてみたい方はTwilioをさわってみてはどうでしょう。

https://twilio.kddi-web.com/

どういう構成だとSTUNでつなぐことが出来て、

TURNが必要になるのはどういう構成なのかなど今度調べてみます。