RaspberryPiでスマートホーム 〜Asteriskで家庭内電話 その2 自動音声メニュー〜
前回、ラズパイにAsteriskをインストールして、IP電話を使った内線通話ができるようになりました。
今回はサポートセンターなどにかけた時によくある「〇〇の場合は1を、□□の場合は2を…」というメニューをAsteriskで作って見ます。
このメニューのことは、自動音声○○、IVR Menuといった呼び方をするようです。自動音声○○の方は”自動音声メニュー”、”自動音声ガイダンス”、”自動音声応答サービス”、”自動音声受付”、”自動音声応答”など、様々な呼び方があって、統一はされてない感じです。
必要なもの
前回の記事の続きで、ラズパイにAsteriskをインストールして内線通話が設定済みの状態から始めて行きます。
メニューを作るにあたって、アナウンス用の音声が必要になります。2つの方法を使って用意しようと思います。
- 電話で録音する
- Google Text To Speechを使う
音声を用意する 〜電話で録音〜
Asteriskでは会話を録音する機能があるので、それを使ってアナウンスを録音し、その録音した音声をメニューで使用する方法です。
/etc/asterisk/extensions.confに録音するダイヤルプランと、録音した音声を確認するダイヤルプランを作成します。401にかけると録音、411にかけると録音したものを再生します。
※一部抜粋。全体は後ほど記載。
1 2 3 4 5 6 7 |
exten => 401,1,Answer() same => n,Record(recordings/test.gsm) same => n,Hangup() exten => 411,1,Answer() same => n,Playback(recordings/test) same => n,Hangup() |
Record()アプリケーションはデフォルトで/usr/share/asterisk/soundsがサウンドの保存場所になっていますので/usr/share/asterisk/sounds/recordings/test.gsmに保存されます。
/usr/share/asterisk/sounds配下には、いくつかフォルダがあるのですが所有者がrootです。このrecordingsというフォルダのみ所有者がasteriskになっているので、おそらくここに保存しろという意図だと思ってここに保存しています(ラズパイのAsteriskはasteriskユーザーで動作しています)。
録音する
これで401に電話すると、ピーっという音がなるので、それに続けて喋ると録音されます。ダイヤルパッドの#を押すと終了です。
録音した音声を確認します。内線411にかけると、保存した音声を再生します。気に入らなかったら内線401にかけて、何度でも録音しましょう。
この方法はIP電話があれば簡単に録音できるので、録音用PCなどを必要としないところが便利です。
音声を用意する 〜Google TTS〜
Googleが提供している、Google Translate Text to Speechというサービスがあります。翻訳した文章をしゃべってくれるというサービスです。そしてそのサービスを使って、音声を再生するPerlスクリプトを作った人がいます。
引数にテキストを渡すことで、任意の文字列をしゃべってくれます。めちゃくちゃ便利です。
まず事前に必要なファイルをパッケージをインストールしておきます。
sudo apt-get install sox mpg123
sudo apt-get install libwww-perl
sudo apt-get install liblwp-protocol-https-perl
続いて上記のサイトからファイルをダウンロードします。Asteriskに必要なのは”googletts.agi”というファイルです。このファイルだけダウンロードしたら使えます。そして/usr/share/asterisk/agi-binにコピーして、Asteriskが実行できるように、chownとchmodしときます。
sudo cp googletts.agi /usr/share/asterisk/agi-bin
sudo chown asterisk:asterisk googletts.agi
sudo chmod u+x googletts.agi
あと、上記のサイトにはAsterisk関係なしに、単体でコマンドラインから実行できるPerlスクリプトがあります。”cli”フォルダの”googletts-cli.pl”です。コマンドラインで、
sudo perl googletts-cli.pl -t "こんにちは" -l ja -s 1.3
と実行すると、”こんにちは”としゃべってくれます。こちらは後日、別の目的に使おうと思っています…
ちなみにオプションは
- -t … 喋らせる言葉。
- -l … 言語。日本語はja。
- -s … 喋るスピード。
実際にしゃべらせてみると音声合成なので若干違和感はありますが、それでも素晴らしいです!ただGoogleの非公式なサービスとのことで、いつ終了するか分からないというところが欠点ではあります。
メニューを作成する
続いて今回の目的のメニューを作成します。これも/etc/astersik/extensios.confにダイヤルプランを記述していくことになります。今回はGoogleTTSを使ってます。
内線301にかけるとアナウンスが流れ、番号の入力を待ちます。1か2を押すと押した番号をしゃべってくれます。9を押すと終了です。それ以外を押すと不正な番号のアナウンスが流れ、メニューに戻ります。
※一部抜粋。全体は後ほど記載。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
exten => 301,1,Goto(menu,s,1) [menu] exten => s,1,Answer() same => n,agi(googletts.agi,"電話ありがとうございます。",ja,any,1.3) same => n(loop),agi(googletts.agi,"1か2を押してください。9で終了します。",ja,any,1.3) same => n,WaitExten() exten => 1,1,agi(googletts.agi,"1を押しました。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) exten => 2,1,agi(googletts.agi,"2を押しました。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) exten => 9,1,agi(googletts.agi,"さようなら。",ja,any,1.3) same => n,Wait(1) same => n,Hangup() exten => i,1,agi(googletts.agi,"その番号はダメです。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) |
[menu]という専用のコンテクストを作ってます。301からGotoでmenuコンテクストのsエクステンションの1行目へ飛ばして、処理しています。
agiアプリケーションで外部ブログラムを実行します。今回は先ほどダウンロードしたgoogletts.agiを呼び出しています。スクリプトの名の後はパラメータをカンマで区切って渡します。googletts.agiの場合は最初に喋らせる言葉、次は言語、次が割り込みに使用する番号、最後が話すスピードです。割り込みは指定しないと、文章を最後まで話終わらないと次に進みません。割り込みの番号を指定すると、アナウンスの途中でも指定された番号が入力された場合は次に進みます。anyならどの番号でも割り込みが可能になります。
n(loop)というのは、loopというラベルです。Goto(s,loop)でsエクステンションのloopラベルへジャンプします。
sとiは特別なエクステンションです。sは今回のようなスタート地点として利用できます。iは現在のコンテクスト”menu”に存在しない番号を押した時に呼び出されます。今回の場合はsエクステンションのloopラベルへGoto()してます。
結局、前回のと合わせてextensions.confの全体はこうなりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
[default] exten => _10Z,1,Dial(SIP/${EXTEN},30,r) same => n,Hangup() exten => 201,1,Answer() same => n,Playback(hello-world) same => n,Hangup() exten => 301,1,Goto(menu,s,1) exten => 401,1,Answer() same => n,Record(recordings/test.gsm) same => n,Hangup() exten => 411,1,Answer() same => n,Playback(recordings/test) same => n,Hangup() [menu] exten => s,1,Answer() same => n,agi(googletts.agi,"電話ありがとうございます。",ja,any,1.3) same => n(loop),agi(googletts.agi,"1か2を押してください。9で終了します。",ja,any,1.3) same => n,WaitExten() exten => 1,1,agi(googletts.agi,"1を押しました。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) exten => 2,1,agi(googletts.agi,"2を押しました。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) exten => 9,1,agi(googletts.agi,"さようなら。",ja,any,1.3) same => n,Wait(1) same => n,Hangup() exten => i,1,agi(googletts.agi,"その番号はダメです。",ja,any,1.3) same => n,Wait(1) same => n,Goto(s,loop) |
ダイアルプランをリロードします。現在起動中のAsteriskに接続します。
sudo asterisk -r
接続すると、Asteriskのプロンプトが表示されます。
Asterisk 11.13.1~dfsg-2+deb8u6, Copyright (C) 1999 - 2013 Digium, Inc. and others.
Created by Mark Spencer
Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.
This is free software, with components licensed under the GNU General Public
License version 2 and other licenses; you are welcome to redistribute it under
certain conditions. Type 'core show license' for details.
=========================================================================
Connected to Asterisk 11.13.1~dfsg-2+deb8u6 currently running on raspberrypi (pid = 680)
raspberrypi*CLI>
”dialplan reload”と入力してエンターを押すと、Dialplan reloadedと表示されます。
raspberrypi*CLI> dialplan reload
Dialplan reloaded.
raspberrypi*CLI>
quitで終了です。
感想
これまた思ったよりも簡単にできてしまいました。凄いです、Asterisk!
こうなると是非ともプログラムと連携させたくなって来ます。押された番号によってプログラムを起動することもできるので、電話を使ったシステムが作れます。