客户案例:使用点星PBX进行电话自助水费查询TTS语音播报原理

1. 功能环境说明

某市区送水公司安装点星PBX呼叫中心,基本的电话功能有:客户呼入请求送水服务,坐席呼出回访,微信公众号使客户可以关注后在线购买桶装水套餐。除了上述功能外,点星PBX还支持客户电话呼入,并通过IVR语音导航调用PHP程序查询客户套餐余额或剩余桶装水数量信息,并通过TTS引擎将查询结果转wav语音文件,再播报给来电客户。

本案例假设信息如下:

送水公司 已经安装点星PBX呼叫中心系统,且系统的对外服务热线号码为: 77778888

版本要求: 需要点星PBX v3.7或以上版本,点星PBX v3.7下载地址:

http://www.dotasterisk.cn/thread-2240-1-1.html

 

2. 由于我们只是给出实现上述功能的原理,所以先给出简单流程图,如下。

本文主要讨论上面绿色流程环节的实现原理和设置。

 

3. 呼叫中心设置

1)在呼叫中心后台菜单【PBX呼叫设置】——【可编程配置】——【可编程目的地】添加一个"自助查询套餐余额"的AGI脚本目的地,如下图。

请注意此处的 "dial分机字符串"字符串要按照规矩提示填写,该字符串必须符合点星PBX的拨号分机规则。后续操作需要自己编写基于该拨号字符串的拨号规则脚本,开发者需要略微懂一点asterisk的拨号规则。

2)新建IVR导航,指定按键3动作的下一步流程为"可编程目的地",如下图。

3)在点星PBX的拨号规则脚本中编写AGI脚本,实现相关功能。此处先编写拨号规则,需要自定义拨号规则的文件如下。

/opt/app/ast/asterisk/exten_program_custom.conf

加入内容如下:

[root@da36:~]#cat  /opt/app/ast/asterisk/exten_program_custom.conf 
[agi-program]
exten => **90000,1,NoOp(-----DEBUG: 来电手机号: ${CALLERID(num)})
exten => **90000,n,AGI(queryRestMoney.php)
exten => h,1,Hangup()

[root@da36:~]#

4)准备一张 测试数据表client_water,表的内容很简单: 三个主要的field为"客户手机号"、"剩余水费"、“剩余桶”。表结构如下。

创建sql表数据如下:

CREATE TABLE `client_water` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `telephone` varchar(16) NOT NULL COMMENT '客户电话',
  `rest_money` int(11) DEFAULT '0' COMMENT '剩余金额(元)',
  `rest_number` int(11) DEFAULT '0' COMMENT '剩余桶装水数量',
  PRIMARY KEY (`id`,`telephone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
预先录入3条数据,以备后续测试,如下图。

上述呼叫流程框架基本设置完成,剩下的主要是php的AGI脚本 queryRestMoney.php 代码编写逻辑。

 

4. 编写AGI脚本 queryRestMoney.php 

1)首先需要安装点星PBX适配的TTS文本转语言引擎,下载地址和安装步骤如下。

下载地址: http://www.dotasterisk.cn/iso/tts-rpms.zip

2) 将下载文件上传到点星PBX,用unzip命令解压,并按照如下步骤安装,如下:

先安装依赖rpm包: rpm -ivh rpm-deps/*.rpm

再安装TTS引擎: rpm  -ivh TTS-2.0.0-2.x86_64.rpm 

如下图。

3). 有两种方式编写AGI脚本。

可以从 https://packagist.org/ 下载 phpagi,然后引入,如下图:

也可以用点星PBX自带的AGI类库进行AGI类对象的初始化,点星自带的AGI类库文件路径为: /opt/app/crm/Common/Libs/Asterisk/AGI.class.php ,原理一样,编码方法大同小异。

下面以 下载的 "d4rkstar/phpagi" 为例子进行代码编写。

首先请将phpagi库里面的 phpagi.php ,phpagi-asmanager.php 两个文件上传到点星PBX的 /opt/app/ast/agi-bin/目录,然后编写AGI脚本 TTS.conf.php 和 queryRestMoney.php,如下。【注意】php脚本务必给执行权限,简单点就是给777权限即可。

先看测试结果,在文章的最后会给出 TTS.conf.php 和 queryRestMoney.php 的源代码。

 

5 测试结果如下。

有php代码调用tts引擎生成的text文本文件和wav文件在目录 /dev/shm/tts/ 下面。

 

 

 

6. 最后给出大家最期待的源码,代码比较简单,仅仅只是说明原理,仅供测试参考。

TTS.conf.php

<?php

	//按键相关配置
    define("TIMEOUT",6000);//输入超时时间,毫秒
    define("TRY_TIMES",3);//输入提示重试次数
	define("DELETE_TMP_TXT_FILE",FALSE);//是否删除脚本生成的txt文件
    define("DELETE_TMP_WAV_FILE",TRUE);//是否删除TTS生成的音频文件
	
	
    //TTS引擎配置
    $TTS_cfg_dir = "/opt/SinoVoice/jTTS-6.0/bin";
    $TTS_bin_file = "/opt/SinoVoice/jTTS-6.0/Example/test/PlayToFile.exe";
    $TTS_tmp_dir = "/dev/shm/tts" ;//本目录权限最好为777,保证asterisk有读写权限
	if( !file_exists($TTS_tmp_dir) )  mkdir($TTS_tmp_dir, 0777);
    
	
	//mysql链接信息配置
	$globalConf = parse_ini_file("/opt/app/pbx_linux.conf", TRUE);
	define ( 'MY_DB_HOST', $globalConf['crm']['hostname'] );
	define ( 'MY_DB_NAME', $globalConf['crm']['dbname'] );
	define ( 'MY_DB_USER', $globalConf['crm']['user'] );
	define ( 'MY_DB_PWD', $globalConf['crm']['password'] );
    $PDO = getPDO();
	
	

    //todo; 待做功能,可以更好的完善整个流程,asterisk拨号计划相关功能码配置
	define("MAIN_MENU_WELCOME","**80000"); //todo: 接通后主菜单Welcome欢迎语
	define("HELP","**80001"); //todo: 人工帮助,将呼叫流程转入人工服务(坐席队列)


	//MySQL的PDO链接
	function getPDO() {
			$dsn = 'mysql:host='. MY_DB_HOST .';port=3306;dbname='. MY_DB_NAME;
			return new PDO($dsn, MY_DB_USER, MY_DB_PWD);
	}
	
	
	//调用TTS生成WAV音频文件。参数$tts_tmp_text是php脚本临时生成的文本文件
	function generateWAV($tts_tmp_text,$tts_tmp_wav){
		global $TTS_tmp_dir,$TTS_bin_file,$TTS_cfg_dir;
		$cmd = "cd /tmp/; $TTS_bin_file WangJing_e 65001 $tts_tmp_text $tts_tmp_wav";
		//$cmd = "cd /tmp/; $TTS_bin_file WangJing_e 65001 $tts_tmp_text $tts_tmp_wav 2>&1";	//调试
		//file_put_contents('/dev/shm/tts/cmd.log',  __FILE__.':'.  $cmd.PHP_EOL, FILE_APPEND);	//调试
		
		$retStr = $retCode = NULL;
		exec($cmd,$retStr,$retCode);
		//file_put_contents('/dev/shm/tts/cmd.log',  __FILE__.':'.  var_export($retStr, true).PHP_EOL, FILE_APPEND);	//调试
		
		if(DELETE_TMP_TXT_FILE){
			unlink($tts_tmp_text);//成功转换成WAV音频文件后,就删掉原来的临时 txt文件
		}
		if($retCode == 0){
			return TRUE;
		}else{
			return FALSE;
		}
	}

	
	//repeat.wav 重新收听请按9,返回上一层请按星号键,返回主菜单请按井号键,如需帮助请按0
	//$lastMenu是上级菜单的功能码,$mainMenu是主菜单的功能码
	function playWavFile($tts_tmp,$cidnum,$playContent,$lastMenu=''){
		global $agi;
		$wav_file = $tts_tmp .".wav";
		$agi->stream_file($tts_tmp,'#');
		$dtmf = NULL; $try = 0;
		do{
			//repeat.wav 音频文件内容为: 重新收听请按9 ,返回上一层菜单请按*号键
			$dtmf = $agi->get_data("custom/repeat",TIMEOUT,1);
			if($dtmf['result'] == '9'){ //重新收听
				$try = 0;
				$agi->stream_file($tts_tmp,'#');
			}elseif($dtmf['result'] == '*'){//返回上一层菜单
				if(empty($lastMenu)){
					$agi->verbose("WARNING: lastMenu has no value,do nothing");
					$try++;//如果没有具体提供上级菜单,就什么也不做
				}else{
					if(DELETE_TMP_WAV_FILE){ //如果定义了删除临时tts生成的文件,那么就在这里删除
						unlink($wav_file);
					}
					$agi->verbose("debug--jump to:	$lastMenu");
					$agi->goto_dest('from-internal',$lastMenu,1);
					exit; //只要是goto语句,必须在下一行用exit;退出脚本,否则脚本继续执行
				}
			}elseif($dtmf['result'] == '' && $dtmf['data'] == ''){//返回主菜单(AGI的get_data函数只能用这种方法捕获井号键,别无他法)
				if(DELETE_TMP_WAV_FILE){ //如果定义了删除临时tts生成的文件,那么就在这里删除
					unlink($wav_file);
				}
				$agi->goto_dest('from-internal',MAIN_MENU_WELCOME,1);
				exit; //只要是goto语句,必须在下一行用exit;退出脚本,否则脚本继续执行
			}else{
				$try ++;
			}
			if($try == 3 && DELETE_TMP_WAV_FILE ){
				unlink($wav_file);
			}
		}while($dtmf['result'] == '9' || $try < 3);
	}
	
	

queryRestMoney.php

#!/opt/php/bin/php -q
<?php
        
		//AGI测试
        require_once("TTS.conf.php");
		require_once("phpagi.php");
        $agi = new AGI();
		$cidnum = $agi->request['agi_callerid']; //获得来电号码
		
		
		//查询数据库
		$result = $PDO->query("SELECT * FROM client_water WHERE telephone='{$cidnum}' LIMIT 1");
		$row = $result->fetch();
		
		
		//假设可以查询到数据
		$tts_tmp = $TTS_tmp_dir ."/" .$cidnum ."_" .time();
		$tts_tmp_text = $tts_tmp .'.txt';
		$tts_tmp_wav = $tts_tmp .'.wav';
		$playContent = '您的账号余额为' .$row['rest_money']. '元,剩余桶装水数量为' .$row['rest_number']. '桶。';
		
		file_put_contents($tts_tmp_text,$playContent);
		if( generateWAV($tts_tmp_text, $tts_tmp_wav) ){
			playWavFile($tts_tmp, $cidnum, $playContent, MAIN_MENU_WELCOME); //传参数必须是$tts_tmp,而不是$tts_tmp_wav,因为播放录音时不需要指出文件后缀.wav
		}
		

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值