2019年8月11日日曜日

VoIPで遊ぶ

興味半分・仕事1/4、なんとなく1/4くらいの感じ。
アナログ電話をいい感じに制御して遊びたくなった。
今頃っ!? 意外としぶとく残っているよ。
こんなのとかいつかは欲しいね
https://www.amazon.co.jp/Asterisk用-TDM410P-Issabel-Freepbx-asterisknow/dp/B01L5MGR9E/ref=lp_4443506051_1_16?srs=4443506051&ie=UTF8&qid=1565275361&sr=8-16
今回は、お試しとして「LINKSYS PAP2T VoIPアダブタ」を入手してみた
https://www.amazon.co.jp/VoIPアダプタ-VBESTLIFE-VoIPゲートウェイ-アナログ電話アダプタ-V2プロトコル/dp/B07KS2P9G4/ref=sr_1_3?__mk_ja_JP=カタカナ&keywords=VoIPアダプタ+VBESTLIFE+VoIPゲートウェイ+IP電話&qid=1565019126&s=electronics&sr=1-3
https://www.voip-info.jp/index.php/Linksys_PAP2T
コール音を日本風に
https://shin.4-u.jp/blog/kaden/135/



外線につなぐつもりも無いし、契約していないので、
PAP2Tと古いスマホで内線電話構築して遊んでみる。

Asteriskインストール

この手順で、とりあえず開発PCに入れてみた。
https://qiita.com/sgrowd/items/dd1fc682718a2a623e4c

まずは相互通話

/etc/asterisk/sip.conf
[general]
context=default
port=5060
bindaddr=0.0.0.0
language=ja
;nat=yes
allowguest=no
allow=ulaw
allow=alaw
allow=gsm

[user1]
type=friend
defaultuser=user1
secret=password1
host=dynamic
canreinvite=no

[user2]
type=friend
defaultuser=user2
secret=password2
host=dynamic
canreinvite=no
/etc/asterisk/extensions.conf
[default]
exten => 1,1,Dial(SIP/user1,30,r)
same  => n,Hangup()

exten => 2,1,Dial(SIP/user2,30,r)
same  => n,Hangup()
Dialの説明はここ
https://www.voip-info.org/asterisk-cmd-dial/

PAP2T




[Proxy]のところにAstersik SIPサーバーのIPを設定した。

スマホ

MIZUDROIDとZoiperを試してみた。
ともに音が小さいなぜだろう。
ZoiperではSetting→Audio→SpeakerGainを0dBから10dBにしてみたら多少良くなった。

自動応答

電話かけたら自動応答をやってみる。
https://scc.kokushin-u.jp/2019/01/19/asterisk-ivr/

音声ファイルの準備

どうやらgsm形式とかulaw形式のファイルを準備する必要があるみたい
https://p--q.blogspot.com/2015/04/soxsound-exchangemp3.html
 sudo apt-get install sox libsox-fmt-all
 どっちか
 sox src.mp3 -r 8000 -c 1 dst.gsm
 sox src.mp3 -r 8000 -c 1 -e u-law -t wav dst.ulaw

設定ファイル

/etc/asterisk/extensions.conf
exten => 3,1,Goto(my-ivr,s,1)
[my-ivr]
exten => s,1,Set(dir=/home/asterisk/)
exten => s,n,Ringing()
exten => s,n,Wait(3)
exten => s,n,Answer()
exten => s,n,Playback(${dir}dst)
https://www.voip-info.org/asterisk-cmd-playback/
https://www.voip-info.org/convert-wav-audio-files-for-use-in-asterisk/

自動応答の実験

3にコールするとdst.gsm/ulawが再生される。
いいね! 音質はお察しくださいって感じ。

AGIで遊んでみる

AGIとはAsterisk Gateway Interfaceという、外部との連携するしくみ
https://www.voip-info.org/asterisk-agi
https://my-scribble.net/raspberrypiでスマートホーム-〜asteriskで家庭内電話-その3-agiでシ/
いろいろな言語で使えるみたい。
Pythonとかちょっと気になるけど、インターネットから遮断されている環境でも使うかもしれないので、使い慣れたPHPで…

phpagi

http://phpagi.sourceforge.net/
https://sourceforge.net/projects/phpagi/files/
これの[phpagi-2.20.tgz]と[phpagi-examples-2.20.tgz]をダウンロード。
phpagi.php - The main phpagi class.
phpagi-asmanager.php - The Asterisk Manager class.
を/usr/share/asterisk/agi-binに保存する。
改行コードとかに注意する。
サンプルとして
dtmf.php
も一緒に保存した。
あとは、
/etc/asterisk/extensions.conf
exten => 5,1,agi(dtmf.php)
いざ電話をかけてみると、喋らないOrz
AGIのデバック方法をいろいろ調べた。
https://www.linux.com/news/debugging-asterisk-agi-phpagi-and-festival
http://www.ne.jp/asahi/davinci/code/asterisk/install/index2.html
どうやらtxt2wavでつまずいている。
https://github.com/leoburd/asterisk/blob/master/phpagi.conf
text2waveってなにさ
http://manpages.ubuntu.com/manpages/bionic/man1/text2wave.1.html
なるほど、テキストを喋ってくれるのね。
せっかくなら日本語が良いなー。
google TTSの例はあったけど、陸の孤島環境でも使いたいので
そんな迷える僕の強い味方OpenJTalkを使わせてもらう。

OpenJTalkの準備

昔苦労してインストールしたような気がするけど、便利になったね。
http://open-jtalk.sp.nitech.ac.jp/
http://thr3a.hatenablog.com/entry/20180223/1519360909
https://qiita.com/lutecia16v/items/8d220885082e40ace252
sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
meiさんもダウンロード
https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/
テスト
https://qiita.com/sukesuke/items/be2a4562bd809ccc0fab
echo "こんにちは" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic/  \
-m /usr/share/hts-voice/mei/mei_normal.htsvoice -ow /dev/stdout | aplay --quiet
8kbpsにしようとしてサンプリング周波数設定したらとんでもないことになった
echo "こんにちは" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic/ \
-m /usr/share/hts-voice/mei2/mei_normal.htsvoice -s 8000 -ow /dev/stdout | aplay --quiet
なので、sox使って変更することにした。

phpagiから呼び出す

といってもちょっと書き換えただけ

phpagi.conf

/etc/asterisk/phpagi.conf
[OpenJTalk]
open_jtalk=/usr/bin/open_jtalk
dic=/var/lib/mecab/dic/open-jtalk/naist-jdic/
htsvoice=/usr/share/hts-voice/mei2/mei_happy.htsvoice
other_option='-r 1.1'

phpagi.php

/usr/share/asterisk/agi-bin/phpagi.php
166行目あたり
        // swift TTS config
        if(!isset($this->config['cepstral']['swift'])) $this->config['cepstral']['swift'] = $this->which('swift');

        // Open JTalk
        if(!isset($this->config['OpenJTalk']['open_jtalk'])) $this->config['OpenJTalk']['open_jtalk'] = $this->OpenJTalk('OpenJTalk');
        if(!isset($this->config['OpenJTalk']['dic'])) $this->config['OpenJTalk']['dic'] = $this->OpenJTalk('dic');
        if(!isset($this->config['OpenJTalk']['htsvoice'])) $this->config['OpenJTalk']['htsvoice'] = $this->OpenJTalk('htsvoice');
        if(!isset($this->config['OpenJTalk']['other_option'])) $this->config['OpenJTalk']['other_option'] = $this->OpenJTalk('other_option');

1334行目あたり
    function text2wav($text, $escape_digits='', $frequency=8000)
    {
        省略
    }

    function open_jtalk($text, $escape_digits='', $frequency=8000)
    {
        $text = trim($text);
        if($text == '') return true;

        $hash = md5($text);
        $fname = $this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR;
        $fname .= 'open_jtalk' . $hash;

        // create wave file
        if(!file_exists("$fname.wav"))
        {
          // write text file
          if(!file_exists("$fname.txt"))
          {
            $fp = fopen("$fname.txt", 'w');
            fputs($fp, $text);
            fclose($fp);
          }

          shell_exec("cat $fname.txt | {$this->config['OpenJTalk']['open_jtalk']} -x {$this->config['OpenJTalk']['dic']} -m {$this->config['OpenJTalk']['htsvoice']}  {$this->config['OpenJTalk']['other_option']} -ow $fname.wav.wk");
          shell_exec("sox $fname.wav.wk -r 8000 $fname.wav");
        }
        else
        {
          touch("$fname.txt");
          touch("$fname.wav.wk");
          touch("$fname.wav");
        }

        // stream it
        $ret = $this->stream_file($fname, $escape_digits);

        // clean up old files
        $delete = time() - 2592000; // 1 month
        foreach(glob($this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR . 'open_jtalk*') as $file)
          if(filemtime($file) < $delete)
            unlink($file);

        return $ret;
    }

dtmf.php

/usr/share/asterisk/agi-bin/dtmf.php
日本語だぜー

#!/usr/bin/php -q
<?php
  set_time_limit(30);
  require('phpagi.php');
  error_reporting(E_ALL);
  //die("Syntax ok\n"); // line A: uncomment for syntax test

  $agi = new AGI();
  $agi->answer();

  $agi->open_jtalk("こんにちわ。今日も暑いですね。");
  do
  {
  //  $agi->text2wav('Enter some numbers and then press the pound key. Press 1 1 1 followed by the pound key to q$
    $agi->open_jtalk("ボタンを押して何か数字を入力してください。終了する場合は、111と入力してください。");
    $result = $agi->get_data('/var/lib/asterisk/sounds/beep', 3000, 20);
    $keys = $result['result'];
    $agi->open_jtalk("あなたが入力したのは $keys です。");
  } while($keys != '111');
  $agi->open_jtalk('さようなら!');
  $agi->hangup();
?>
とりあえず今日はここまで。

0 件のコメント:

コメントを投稿