#!/usr/bin/perl -w sub parse_mrcp_json { use Data::Dumper; use LWP::Simple; #use XML::Simple; use Encode qw/encode decode/; use strict; use LWP::UserAgent; use JSON; use utf8; use Encode; use URI::Escape; use DBI; my $self=shift; my $AGI=$self->{server}{agi}; my $PARAM=$self->{server}{params}; #连接数据库 #my $dbh = $self->database_pconnect(); #$dbh->do("SET NAMES 'utf8'"); #${RECOGSTATUS}, ${RECOG_COMPLETION_CAUSE}, ${RECOG_RESULT} my $recog_completion_cause = $AGI->get_variable('RECOG_COMPLETION_CAUSE'); my $recog_result = $AGI->get_variable('RECOG_RESULT'); if ($recog_completion_cause eq "000" || $recog_result) { $self->do_recog_result($recog_result); return; } elsif ($recog_completion_cause eq "002" || $recog_result) { $self->get_respose_voice("", "customerTimeout"); return; } } sub do_recog_result { my $self = shift; my $recog_result = shift; my $AGI=$self->{server}{agi}; #Encode::_utf8_on($recog_result); #my $json_string = encode_json($recog_result); #{"header":{"namespace":"SpeechRecognizer","name":"RecognitionCompleted","status":20000000, # "message_id":"8af3da23efd74d5987356051715e9fbb","task_id":"1d869334359b45c7819f4b912ec32b73", # "status_text":"Gateway:SUCCESS:Success."}, #"payload":{"result":"喂喂喂喂喂。","duration":1530}} my $respj = decode_json($recog_result); if ($respj) { if (exists $respj->{"header"} && exists $respj->{"payload"}) { my $status = $respj->{"header"}{"status"}; my $result = $respj->{"payload"}{"result"}; if ($status == 0 || $status == 20000000) { if ($result) { $AGI->verbose("$result", 3); $self->get_respose_voice($result, "rasr"); } } } } } sub do_tts { ## 需要如下7个参数 参数顺序不能乱 my $self = shift; my $text = shift; my $AGI=$self->{server}{agi}; #$AGI->set_variable("PROMRTFILE","${private_dir}${xml_name}"); } # 入参 #event string 事件(rasr:语音 customerTimeout:静默超时) true - #eventTime int64 事件产生时间,注:事件产生unix时间戳精准到ms true - #text string 对话文本 true - #uniqueId string 本通话唯一标识 true - #playStatus string 当前是否在播放语音中("1":正在播报语音 "0":播报完毕等待中 "-1":通话已结束或其他错误) true - #extraParams string 透传字段 true - # # # 返回值 # code string 响应码 ‘00’代表成功,其他失败 - # message string 响应信息 # data object 响应体 # └─playObject string # 网络音频链接 # 注:当音频链接是个数大于1个时,音频链接之间 # 用逗号隔开,依次播放 # - # └─key string "1.2"正常等待,"1.9"挂断,"1.4"转人工 - # └─transferNumber string # 转人工号码 # keyCall =1.4的时候转接 如:13711111111 # - # └─type string # 播放类型 # play: 打断播放新语音, # next:播放下一段语音, # playCustomerWait:等待当前用户说完话后在播 # 报新语音(在未播报语音前,后一个语音会覆盖前面 # 的语音,只播报最新的一条语音), # ignore:忽略当前动作,不作响应 # - # └─variables map 扩展变量信息 - # └─any object object any object. sub get_respose_voice { my $self = shift; my $text = shift; my $event = shift; my $AGI=$self->{server}{agi}; my $PARAM=$self->{server}{params}; my $uniqueId = $PARAM->{'callerid'}; my $curTime = int(time()*1000); my $url = "https://service-gateway.houxikeji.com/robotcall/callback/dialog/mingyiyun"; my %postjson = ( "event" => "$event", "eventTime" => $curTime, "text" => "$text", "uniqueId" => "$uniqueId", "playStatus" => "0", "extraParams" => "" ); my $extraParams = $AGI->get_variable("extraParams"); if ($extraParams) { $postjson{"extraParams"} = $extraParams; } my $content_string = encode_json(\%postjson); #判断api接口失败次数 my $ttsapi_err_times = $AGI->get_variable("ttsapi_err_times"); if (!$ttsapi_err_times) { $ttsapi_err_times = 0; } #调用app指定的url my $ua = LWP::UserAgent->new(env_proxy => 1, keep_alive => 1, timeout => 10); $ua->agent('perl/5.16'); my $req = HTTP::Request->new('POST' => $url); #$req->header('x-request-time' => $curTime); $req->content_type('application/json;charset=utf-8'); $req->content($content_string); $content_string =~ s/[\s+\r+\n+]//g; $AGI->verbose("$content_string"); my $response = $ua->request($req); if (!$response-> is_success){ $ttsapi_err_times += 1; $AGI->set_variable("ttsapi_err_times", $ttsapi_err_times); $AGI->verbose("$url Post failed: ".$response->status_line, 1); return -1; } my $resl = $response->content(); $resl =~ s/[\s+\r+\n+]//g; $AGI->verbose("---------resl=[$resl]", 1); my $respj = decode_json($resl); if ($respj && exists $respj->{"code"} && "00" eq $respj->{"code"}) { my $data = $respj->{"data"}; if ($data) { my $dstkey = $data->{"key"}; my $wavurl = $data->{"playObject"}; my $filename; if ($wavurl) { $filename = $self->savefile($wavurl, $uniqueId); $AGI->set_variable("ttsapi_err_times", 0); } $AGI->verbose("---------key=[$dstkey] $wavurl $filename", 1); if ($dstkey && "1.9" eq "$dstkey") { #set_context #$AGI->set_extension() if ($filename) { $AGI->exec("Playback", "$filename"); } $AGI->set_priority("hup"); return 0; } } return 0; } $ttsapi_err_times += 1; $AGI->set_variable("ttsapi_err_times", $ttsapi_err_times); return -1; } sub savefile() { my $self = shift; #my $wavurl = "https://hx-robot-call.oss-cn-shanghai.aliyuncs.com/robot-call/record_wav/ttsRecord/16253_2024-04-19_7d2765327f3c41f2a640a5ab82683801.wav"; my $wavurl = shift; my $callerid = shift; my $AGI=$self->{server}{agi}; #my $filename = `basename $wavurl`; #$filename =~ s/^\s+|\s+$//g; my $filedir = "/data/justcall/pbx/lib/sounds/mrcpvoice/"; my $playfile = $filedir.$callerid.time; my $filename = "$playfile.wav"; my $ua = LWP::UserAgent->new(env_proxy => 1, keep_alive => 1, timeout => 10); my $response = $ua->get($wavurl); if ($response->is_success) { my $content_type = $response->content_type; my $content_length = $response->content_length; if ($content_type =~ /audio/ || $content_type =~ /wav/) { $AGI->verbose("new $filename => $content_type $content_length", 1); if ($content_length && $content_length > 0) { my $WAVFILE; open($WAVFILE, "+>", $filename) or return; print $WAVFILE $response->decoded_content; $WAVFILE->flush(); close($WAVFILE); if ( -e $filename) { my $oldfile = $AGI->get_variable("PROMRTFILE"); if ( -e $oldfile) { unlink $oldfile; $AGI->verbose("replace PROMRTFILE from $oldfile to $filename", 1); } else { $AGI->verbose("set PROMRTFILE $filename", 1); } $AGI->set_variable("PROMRTFILE","$filename"); return $playfile; } } } } else { $AGI->verbose("$wavurl failed: ".$response->status_line, 1); } return; }