先说说我都使用了哪些办法1.开通微信的语音识别功能进行尝试,使用订阅号自己的微信识别功能。可惜效果并不能令人满意识别率很低。
2.接收到微信的语音并不通过微信的识别,通过临时素材接口把文件保留下来然后接入阿里的语音识别,由于阿里的语音识别不能直接读取amr的文件需要转码,导致效率有点低。
3.也是将微信的语音素材保存到服务器,直接保存为amr文件然后接入百度的语音识别,百度语音识别出来的文字再发送到阿里的知识库收到返回结果显示出来,这条路可以,反应速到也能接受
4.期间还尝试了其他的第三方平台:图灵机器人、讯飞微信服务等。
下面就记录一下期间遇到的坑:
1.微信对接服务器的方法和接口微信的api中都有写,给的demo并不友好。在网上查找资料后发现有比较好的方式,使用后发现并不能流程工作几次过后都有提示无法服务的消息。原因:消息返回的调用位置不对,导致并不是每次都可以有数据返回
2.在下载素材时应该把接收到的包都保存下来,不能只存body,附上代码
private function downloadWeiXinFile($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$package = curl_exec($ch);
curl_close($ch);
return $package;
}
最后附上完整代码,由于是php新手,所以代码都写到了一个文件里边
<?php
define("TOKEN", "***");
$wechatObj = new wechatCallbackapiTest();
$wechatObj->valid();
function getAccessToken()
{
// access_token 应该全局存储与更新,以下代码以写入到文件中做示例
$data = json_decode(file_get_contents("./**.json"));
if ($data->expire_time < time()) {
$appid = "*"; //自己的appid
$appsecret = "***"; //自己的appsecret
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
$res = json_decode(httpGet($url));
$access_token = $res->access_token;
if ($access_token) {
$data->expire_time = time() + 7000;
$data->access_token = $access_token;
$fp = fopen("./***.json", "w");
fwrite($fp, json_encode($data));
fclose($fp);
}
} else {
$access_token = $data->access_token;
}
return $access_token;
}
//HTTP get 请求
function httpGet($url)
{
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
class wechatCallbackapiTest
{
//验证消息
public function valid()
{
$echoStr = $_GET["echostr"];
if ($this->checkSignature()) {
echo $echoStr;
$this->responseMsg();
exit;
}
}
//检查签名
private function checkSignature()
{
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$token = TOKEN;
$tmpArr = array(
$token,
$timestamp,
$nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
//响应消息
public function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"]; //获取微信端发送的xml数据
if (!empty($postStr)) {
//将$postStr变量进行解析,并赋予$postObj
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$RX_TYPE = trim($postObj->MsgType);
switch ($RX_TYPE) {
case "event":
// $result = $this->receiveEvent($postObj);
break;
case "text":
$result = $this->receiveText($postObj);
break;
case "image":
$result = $this->receiveImage($postObj);
break;
case "location":
$result = $this->receiveLocation($postObj);
break;
case "voice":
$result = $this->receiveVoice($postObj);
break;
case "video":
$result = $this->receiveVideo($postObj);
break;
case "link":
$result = $this->receiveLink($postObj);
break;
default:
$result = "unknown msg type: " . $RX_TYPE;
break;
}
echo $result;
} else {
echo "";
exit;
}
}
//接收事件消息(6个)
private function receiveEvent($object) //这里的$object来自$postObj————解析了微信消息的对象
{
$content = "";
$result = $this->transmitText($object, $content);
return $result;
}
//接收文本消息
private function receiveText($object)
{
$Answer = ali($object->Content);
if ($Answer != null) {
$content = $Answer;
} else {
$content = "请重新提问";
}
//$content=$object->Content;
$result = $this->transmitText($object, $content);
return $result;
}
//接收图片消息
private function receiveImage($object)
{
$content = array("MediaId" => $object->MediaId);
$result = $this->transmitImage($object, $content);
return $result;
}
//接收位置消息
private function receiveLocation($object)
{
$content = "你发送的是位置,纬度为:" . $object->Location_X . ";经度为:" . $object->Location_Y .
";缩放级别为:" . $object->Scale . ";位置为:" . $object->Label;
$result = $this->transmitText($object, $content);
return $result;
}
//接收语音消息
private function receiveVoice($object)
{
//
// if (isset($object->Recognition) && !empty($object->Recognition)) {
// $Answer = ali($object->Recognition);
// if ($Answer != null) {
// $content = "识别结果:" . $object->Recognition . "\n" . $Answer;
// } else {
// $content = "识别结果:" . $object->Recognition;
// }
// // $content ="识别结果:".$object->Recognition.;
// $result = $this->transmitText($object, $content);
// } else {
// $content = array("MediaId" => $object->MediaId);
// $result = $this->transmitVoice($object, $content);
// }
$access_token = getAccessToken();
$mediaId = $object->MediaId;
$fileurl = "https://api.weixin.qq.com/cgi-bin/media/get?access_token=$access_token&media_id=$mediaId";
$content = $this->downloadWeiXinFile($fileurl);
$filename = "voice.amr";
$this->saveWeiXinFile($filename, $content);
$text=Bd_Asr();
$Answer="识别结果:" . $text . "\n".ali($text);
$result = $this->transmitText($object, (string )$Answer);
return $result;
}
//接收视频消息
private function receiveVideo($object)
{
$content = array(
"MediaId" => $object->MediaId,
"ThumbMediaId" => $object->ThumbMediaId,
"Title" => "",
"Description" => "");
$result = $this->transmitVideo($object, $content);
return $result;
}
//接收链接消息
private function receiveLink($object)
{
$content = "你发送的是链接,标题为:" . $object->Title . ";内容为:" . $object->Description .
";链接地址为:" . $object->Url;
$result = $this->transmitText($object, $content);
return $result;
}
//接入多客服
private function transmitKefu($object)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回复文本消息
private function transmitText($object, $content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time(),
$content);
return $result;
}
//回复图片消息
private function transmitImage($object, $imageArray)
{
$itemTpl = "<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>";
$item_str = sprintf($itemTpl, $imageArray['MediaId']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回复语音消息
private function transmitVoice($object, $voiceArray)
{
$itemTpl = "<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>";
$item_str = sprintf($itemTpl, $voiceArray['MediaId']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回复视频消息
private function transmitVideo($object, $videoArray)
{
$itemTpl = "<Video>
<MediaId><![CDATA[%s]]></MediaId>
<ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
</Video>";
$item_str = sprintf($itemTpl, $videoArray['MediaId'], $videoArray['ThumbMediaId'],
$videoArray['Title'], $videoArray['Description']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[video]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//回复图文消息
private function transmitNews($object, $newsArray)
{
if (!is_array($newsArray)) {
return;
}
$itemTpl = " <item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>
";
$item_str = "";
foreach ($newsArray as $item) {
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'],
$item['Url']);
}
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<Content><![CDATA[]]></Content>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str</Articles>
</xml>";
$result = sprintf($newsTpl, $object->FromUserName, $object->ToUserName, time(),
count($newsArray));
return $result;
}
//回复音乐消息
private function transmitMusic($object, $musicArray)
{
$itemTpl = "<Music>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<MusicUrl><![CDATA[%s]]></MusicUrl>
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>";
$item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'],
$musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
$item_str
</xml>";
$result = sprintf($textTpl, $object->FromUserName, $object->ToUserName, time());
return $result;
}
//获取文件信息
private function downloadWeiXinFile($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOBODY, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$package = curl_exec($ch);
//$httpinfo = curl_getinfo($ch);
curl_close($ch);
//$result = array_merge(array('header' => $httpinfo), array('body' => $package));
return $package;
}
//保存文件
private function saveWeiXinFile($filename, $filecontent)
{
$local_file = fopen($filename, 'w');
if (false !== $local_file) {
if (false !== fwrite($local_file, $filecontent)) {
fclose($local_file);
}
}
}
}
//百度语音识别
function Bd_Asr()
{
define('AUDIO_FILE', "voice.amr");
$url = "http://vop.baidu.com/server_api";
//put your params here
$cuid = "***";
$apiKey = "***";
$secretKey = "***";
$auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" .
$apiKey . "&client_secret=" . $secretKey;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $auth_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
$response = curl_exec($ch);
if (curl_errno($ch)) {
print curl_error($ch);
}
curl_close($ch);
$response = json_decode($response, true);
$token = $response['access_token'];
$audio = file_get_contents(AUDIO_FILE);
$base_data = base64_encode($audio);
$array = array(
"format" => "amr",
"rate" => 8000,
"channel" => 1,
//"lan" => "zh",
"token" => $token,
"cuid" => $cuid,
//"url" => (string)$amrurl,
//"callback" => "http://www.xxx.com/audio/callback",
"len" => filesize(AUDIO_FILE),
"speech" => $base_data,
);
$json_array = json_encode($array);
$content_len = "Content-Length: " . strlen($json_array);
$header = array($content_len, 'Content-Type: application/json; charset=utf-8');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POSTFIELDS, $json_array);
$response = curl_exec($ch);
if (curl_errno($ch)) {
print curl_error($ch);
}
curl_close($ch);
echo $response;
$response = json_decode($response, true);
var_dump($response);
return $response['result'][0];
}
//阿里语音转文字
function TranTextPost()
{
$akId = "***";
$akSecret = "***";
$turl = "https://nlsapi.aliyun.com/transcriptions";
$arr = array(
'app_key' => "nls-service-telephone8khz",
'oss_link' => "",
'auto_split' => false);
$options = array('http' => array(
'header' => array(
'accept' => "application/json",
'content-type' => "application/json",
'date' => gmdate("D, d M Y H:i:s \G\M\T"),
'authorization' => ''),
'method' => "POST", //可以是 GET, POST, DELETE, PUT
'content' => json_encode($arr)));
$http = $options['http'];
$header = $http['header'];
$body = $http['content'];
if (empty($body))
$bodymd5 = $body;
else
$bodymd5 = base64_encode(md5($body, true));
$stringToSign = $http['method'] . "\n" . $header['accept'] . "\n" . $bodymd5 . "\n" .
$header['content-type'] . "\n" . $header['date'];
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $akSecret, true));
$authHeader = "Dataplus " . "$akId" . ":" . "$signature";
$options['http']['header']['authorization'] = $authHeader;
$options['http']['header'] = implode(array_map(function ($key, $val)
{
return $key . ":" . $val . "\r\n"; }
, array_keys($options['http']['header']), $options['http']['header']));
$context = stream_context_create($options);
$file = file_get_contents($turl, false, $context);
$arrayAns = json_decode($file, true);
$file = $arrayAns['id'];
return $file;
}
function TranTextGet($id)
{
$akId = "***";
$akSecret = "***";
$turl = "https://nlsapi.aliyun.com/transcriptions/" . $id;
$options = array('http' => array(
'header' => array(
'accept' => "application/json",
'content-type' => "application/json",
'date' => gmdate("D, d M Y H:i:s \G\M\T"),
'authorization' => ''),
'method' => "GET",
'content' => ''));
$http = $options['http'];
$header = $http['header'];
$body = $http['content'];
if (empty($body))
$bodymd5 = $body;
else
$bodymd5 = base64_encode(md5($body, true));
$stringToSign = $http['method'] . "\n" . $header['accept'] . "\n" . $bodymd5 . "\n" .
$header['content-type'] . "\n" . $header['date'];
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $akSecret, true));
$authHeader = "Dataplus " . "$akId" . ":" . "$signature";
$options['http']['header']['authorization'] = $authHeader;
$options['http']['header'] = implode(array_map(function ($key, $val)
{
return $key . ":" . $val . "\r\n"; }
, array_keys($options['http']['header']), $options['http']['header']));
$context = stream_context_create($options);
$file = file_get_contents($turl, false, $context);
$arrayAns = json_decode($file, true);
$file = $arrayAns['status'];
return $file;
}
//阿里知识库查询
function ali($Question)
{
$akId = "***";
$akSecret = "***";
$url = "https://nlsapi.aliyun.com/qas?";
//更新api信息
$arr = array(
'version' => "2.0",
'app_key' => "nui-c2yidv3u",
'question' => (string )$Question);
$options = array('http' => array(
'header' => array(
'accept' => "application/json",
'content-type' => "application/json",
'date' => gmdate("D, d M Y H:i:s \G\M\T"),
'authorization' => ''),
'method' => "POST", //可以是 GET, POST, DELETE, PUT
'content' => json_encode($arr) //如有数据,请用json_encode()进行编码
));
$http = $options['http'];
$header = $http['header'];
$body = $http['content'];
if (empty($body))
$bodymd5 = $body;
else
$bodymd5 = base64_encode(md5($body, true));
$stringToSign = $http['method'] . "\n" . $header['accept'] . "\n" . $bodymd5 . "\n" .
$header['content-type'] . "\n" . $header['date'];
$signature = base64_encode(hash_hmac("sha1", $stringToSign, $akSecret, true));
$authHeader = "Dataplus " . "$akId" . ":" . "$signature";
$options['http']['header']['authorization'] = $authHeader;
$options['http']['header'] = implode(array_map(function ($key, $val)
{
return $key . ":" . $val . "\r\n"; }
, array_keys($options['http']['header']), $options['http']['header']));
$context = stream_context_create($options);
$file = file_get_contents($url, false, $context);
$arrayAns = json_decode($file, true);
$result = $arrayAns["answers"][0]["answer"];
echo ($result);
return $result;
}
?>