Help us understand the problem. What is going on with this article?

Twilioを使って、二者間の通話に別の音声を挿入する

More than 3 years have passed since last update.

要約

Twilioを使った二者間通話をしているときに、例えば「あと1分で通話が終了します」のような音声をプログラムから流すことができます。
意外と問い合わせの多い機能で、本日実現方法を見つけたので、記事にしておきます。

前提

  • Twilioアカウントを保有していること
  • PHPやNodeなど、Twilioヘルパーライブラリを使って簡単なプログラムがかけること
  • 050番号を2つ以上持っていること
  • TwiMLを返すことができるサーバーを持っていること(Twimlbinでも構いません)

手順(概要)

  1. Twilioのカンファレンス機能を使って、まずは二者間で通話を実現します。
  2. 音声を挿入したいタイミングでRestAPIを使って、050番号にダイヤルします。
  3. 050番号の着信後、TwiMLでカンファレンスにリダイヤルします。
  4. カンファレンスに参加したタイミングを見計らって、2の発信呼でSay動詞のTwiMLを呼びます。
  5. Sayが終了した時点で、050番号は切断されます。

Let's TRY

カンファレンスを用意する

050番号を2つ用意します。
そのうち1つ(以後、カンファレンス番号)に、以下のTwiMLを返すURLを設定します。

TwiML
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial callerId='+815XXXXXXXXX'> ←カンファレンス番号を指定します
    <Conference beep="false" waitUrl="" startConferenceOnEnter="true" endConferenceOnExit="true">
      test
    </Conference>
  </Dial>
</Response>

カンファレンス番号に着信すると、testというカンファレンスに参加するTwiMLです。
beep="false"にしているので、カンファレンスに参加したり抜けたりする先に音がなりません。また、カンファレンスに参加した時点で相手との通話が始まり、どちらからが通話を切った時点で、お互いの通話が切れるように設定してあります。

挿入したい音声を再生するTwiMLを用意する

例えば、以下のようなTwiMLを用意して、これを返すURLを別途控えておきます。

TwiML
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Pause length="2"/>
  <Say language='ja-jp'>あと3分で終了です。</Say>
</Response>

ポイントは、Say動詞の前にPauseを入れている点です。この後説明する、カンファレンスへの参加作業に少しだけ時間がかかるので、ポーズをいれないと最初の方の音声がうまく再生されません。今回は2秒待ってから発声するようにしています。

RestAPIから発信した際に、最初に返すTwiMLを用意する

もう一つの050番号(以下、音声挿入番号)に対して、以下のTwiMLを返すようにしておきます。

TwiML
<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Dial callerId="+815XXXXXXXXX"> ←音声挿入番号を指定します
    <Conference beep="false">test</Conference>
  </Dial>
</Response>

カンファレンス参加用のTwiMLとほぼ同じですが、会話を抜けてもカンファレンスが終わらないようにしています。

RestAPIを使って、発信するプログラムを作成する

PHPやNode.jsなど、RestAPIをコールできる言語を使って、次のようなプログラムをコーディングします。今回はNode.jsで書きました。

Node.js
var accountSid = 'ACXXXXXXXXXXXXXXX'; ←ご自分のAccount SIDに変更してください
var authToken = "XXXXXXXXXXXXXXX"; ←ご自分のAuth Tokenに変更してください
var client = require('twilio')(accountSid, authToken);

client.calls.create({
    url: "http://xxxxxxxxxxx", ←先ほど作成した音声再生用のURLを指定します
    to: "+8150XXXXXXXX", ←音声挿入番号を指定します
    from: "+8150XXXXXXXX" ←カンファレンス番号を指定します
}, function(err, call) {
    process.stdout.write(call.sid);
});

RestAPIでコールをかけるプログラムになっています。発信先番号が音声挿入番号になっているので、着信後にカンファレンスに参加するようになっています。
それと同時に、着信した際にurlで指定した音声再生用TwiMLも実行されるので、結果として、カンファレンスに参加して音声が流れます。音声再生が終わると、TwiMLがすべて終了するので、RestAPIで発信したコールは自動的に終了します。

まとめ

今回のポイントは以下のとおりです。

  • RestAPIから直接カンファレンスに参加することはできません。
  • そのため、一度050番号に発信してTwiMLを呼び出し、そこからカンファレンスに参加します。
  • RestAPIでかけた際に、着信したときに実行されるurlで音声を流しますが、この時点ではカンファレンスへの接続が完了していない可能性があり、音声を少し遅らせてから再生しています。
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away