そろそろ正月休みも終盤である。
休み中に作った環境を壊す前にAsterisk+IBM Watson TTSのちょっとした実験として、任意の文字列を音声ファイルに変換して、電話をかけてその音声ファイルを再生する、というのをやっておきたいと思った。
まあ、仕事だったらPagerDutyとか使えよというものであるが、外線電話でなく自前のAsteriskにつながったSIPフォンに掛けられるとすれば需要があるかもというもの。
環境は先日の記事を参照。
Webhookを作る
単にシェルスクリプトでも良かったのだが、監視システムとの連携を考えるとWebhookになっていた方がいいかと思い、それで。
ruby sinatraでAsteriskサーバー上に実装。
# apt-get install ruby
# gem install sinatra --no-ri
あと、音声ファイル変換にsoxが必要。
# apt-get install sox
以下のファイルを作成する。
APIKEY、エンドポイントのURLはIBM CloudのTextToSpeechサービスの管理画面から手に入る。
音声ファイルをSIPフォン6001番に発信するようになっているが、番号はAsteriskから掛けられるものなら何でも。Twilio経由で外線でもいい。はず。
SSMLとかAccept:audio/wav;rate=8000
とかはまあ、ググれば出てくる。
APIKEY = "<APIKEY>"
TTS_SERVER = "<エンドポイントのURL>"
require "sinatra"
require "json"
set :bind, "0.0.0.0"
set :port, 8888
post "/" do
content_type 'application/json'
File.open($0 + ".flock", "w") do |f|
f.flock File::LOCK_EX
r = (JSON.parse request.body.read)["text"]
ssml = '<speak><break time=\\"1500ms\\"></break>' \
+ r.gsub('"', '').gsub("'", "") + '</speak>'
puts ssml
command = 'curl -X POST -H "Content-type:application/json" -H "Accept:audio/wav;rate=8000" -d \'{"text":"' + ssml + '"}\' -u "apikey:' + APIKEY + '" ' + TTS_SERVER + '/v1/synthesize?voice=ja-JP_EmiV3Voice -o 6001.wav'
`#{command}`
`sox 6001.wav 6001.gsm`
`mv 6001.gsm /var/lib/asterisk/sounds/en/6001.gsm`
`cp callfile /var/spool/asterisk/outgoing/callfile`
`rm 6001.wav`
end
end
Asteriskの自動発信は、callfileというファイルを/var/spool/asterisk/outgoing
に配置することで行う。
https://wiki.asterisk.org/wiki/display/AST/Asterisk+Call+Files
今回使用するファイルは以下。
Channel: PJSIP/6001
Application: Playback
Data: 6001
ここまで出来たら、以下のコマンドを実行してWebhook宛先サーバーとなるプログラムを起動する。
# ruby textcall.rb
試す
別のsshクライアントでAsteriskサーバーに繋げ直し、curlコマンドを以下の通り実行する。
# curl -X POST -d '{"text":"ぉおーまえのかーちゃんでーべそ!"}' -H "Content-type:application/json" localhost:8888
SIPフォン6001番(私の環境ではJitsi Meetサーバーだが)に電話がかかり、正しくメッセージが読み上げられただろうか?