ABCD+Wトーン対応！DTMFトーンの送受信をNode.jsで試してみた



2024年5月、TwilioからDTMF（プッシュ信号）に関するアップデートが発表されました。

[Changelog: DTMF Support for A, B, C, D, and W tones](https://www.twilio.com/en-us/changelog/dtmf-support-ABCD-W)

これにより、Play動詞で `A〜D` や `w/W` のDTMFトーンが正式にサポートされるようになりました。  これまで `0〜9` と `*#` しか使っていなかった方にとっては、思わぬ発見かもしれません。
実は自分もTwilioを5年以上使っていますが、このDTMFに数字以外の入力ができることを全く知りませんでした。今回のアップデートをきっかけに、実際に数字以外のDTMFトーンを送受信するサーバーをExpressで構築し、試してみました。
ちなみに、2025年5月20日時点のTwilio Programmable Voice Javascript sdkでは**未対応**です。
現時点で対応しているのは、
- <Play> 動詞の digits 属性(TWIML)
- <Dial><Number> の sendDigits 属性(TWIML)
- Call Resource の SendDigits パラメーター(REST API)
- Twilio Studio の Say/Play ウィジェット内の Digits
- Twilio Studio の Make Outgoing Call ウィジェット内の Send digits ￼ ￼

---

## 構成と目的

今回は以下のようなシンプルな構成で検証を行います。

- Twilio APIから電話を発信（curl）
- `/make-call` エンドポイントでDTMFを自動送信
- `/incoming-call` 側でDTMFの入力を受け取り、ログに出力

### 事前準備
- Twilioアカウント
- 電話番号を２個購入済み
- Node
- ngrok
- curl

---

## Node.js (Express) 実装

### コード

まずはExpressサーバーをセットアップします。

```bash
npm init -y
npm install express body-parser
```

```js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));

// Twilioからの発信時にDTMFトーンを自動送信
app.post('/make-call', (req, res) => {
  res.type('text/xml');
  res.send(`
    <Response>
      <Pause length="3"/>
      <Play digits="0923712w3WABCD#"/>
    </Response>
  `);
});

// 着信時にDTMF入力を促す
app.post('/incoming-call', (req, res) => {
  res.type('text/xml');
  res.send(`
    <Response>
      <Gather action="/dtmf-handler" method="POST" numDigits="20" finishOnKey="#">
        <Say>DTMFトーンを入力してください。最後にシャープを押してください。</Say>
      </Gather>
      <Say>入力がありませんでした。</Say>
    </Response>
  `);
});

// DTMFを受信した際の処理
app.post('/dtmf-handler', (req, res) => {
  const digits = req.body.Digits;
  const callSid = req.body.CallSid;
  console.log(`[DEBUG] CallSid: ${callSid}, DTMF received: ${digits}`);
  res.type('text/xml');
  res.send(`
    <Response>
      <Say>入力されたDTMFは ${digits} でした。</Say>
    </Response>
  `);
});

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});
```

### サーバーの起動

このサーバをnpmで起動します。
```bash
npm start or node server.js
```

ngrokを使って公開します。
``` bash
node http 3000 --subdomain=testsubdomain
```

## Twilio側の設定
次にTwilioコンソールで着信する電話番号に、上記のサーバで構築したTwiMLのURLを設定します。

1. Twilioコンソールにアクセス
2. Phone Numbers→Manage→Active Numbersで今回受電で使う電話番号をクリック
3. Configureタブ
4. A Call Comes inをWebhookで設定、URLにNgrokのURL＋サーバで作った「/incoming-call」を入れる
```
htttps://<subdomain>.jp.ngrok.io/incoming-call
```
![SCR-20250520-nqnm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649595/b4b03129-938e-4451-b8a4-eec0e0090a7b.png)



---


## 電話を発信
### curlコマンド

TwilioのREST APIを使って電話を発信し、指定エンドポイントにアクセスさせます。

```bash
curl -X POST https://api.twilio.com/2010-04-01/Accounts/<account_sid>/Calls.json \
  --data-urlencode "To=+8150XXXXXXX" \
  --data-urlencode "From=+8150YYYYYYY" \
  --data-urlencode "Url=https://your-ngrok-url.ngrok.io/make-call" \
  -u <account_sid>:<your_auth_token>
```
|パラメータ|説明|値|
|--------|----|-----|
|To|電話の架電先番号|+8150XXXXXXX(Twilioの電話番号#1)|
|From|電話のかけ元番号|+8150YYYYYYY(Twilioの電話番号#2)|
|Url|TwimlのURL|https://\<subdomain\>.jp.ngrok.io/make-call|

---

### DTMFトーンの種類と意味

| トーン | 説明 |
|--------|------|
| A〜D   | 特殊な音声通信機器制御、レガシーPBXや軍用装置向けに設計されたトーン |
| w      | 0.5秒の待機を意味するポーズ |
| W      | 1秒の待機を意味するポーズ |

これらのトーンを組み合わせることで、より複雑なIVRシナリオや、レガシー機器とのインターフェースを構築することが可能になります。

---

## 実行結果

DTMFトーンを送信後、受信側のログに以下のように表示されます。

```bash
[DEBUG] CallSid: CAxxxxxxxxxxxxxxxx, DTMF received: 09237123WABCD#
```

また、音声ガイダンスで「入力されたDTMFは 09237123WABCD# でした」と返されます。

---

## 使用頻度とユースケースについて

Twilioユーザーの多くは `0〜9`、`*`、`#` のトーンで十分なケースがほとんどです。  
しかし、以下のような場面では `A〜D` や `w/W` トーンが必要になるそうです。

- 特殊なIVRメニューの制御
- 古いPBXや独自開発の音声装置との接続
- ハードウェアデバイスやゲート制御機器へのコマンド送信
- システムの応答速度に合わせたDTMF送信の調整

実際の使用頻度は高くないかもしれませんが、「既存システムとの連携」や「特定のプロトコル要件」に直面したときに、このアップデートが非常に重要になる場面があります。

もしあなたの業務で、レガシーIVRやハードウェア制御機器と接続するような場面があれば、今回のアップデートが突破口になる可能性があります。

---

## まとめ

- TwilioがPlay動詞でのABCD/Wトーン送信に対応
- Node.js + Expressで送受信の実装は容易
- 特定の業務や既存システムとの接続において、この機能が有効に活用できる

今まで使ったことがない方も、検証環境でぜひ一度試してみることをおすすめします。

---

## 関連リンク

- [Changelog: DTMF Support for A, B, C, D, and W tones](https://www.twilio.com/en-us/changelog/dtmf-support-ABCD-W)
- [TwiML `<Play>` ドキュメント](https://www.twilio.com/docs/voice/twiml/play)
- [TwiML `<Gather>` ドキュメント](https://www.twilio.com/docs/voice/twiml/gather)