美文网首页
微信订阅号语音识别功能的开发

微信订阅号语音识别功能的开发

作者: 自洽十点 | 来源:发表于2017-04-18 12:03 被阅读0次

    先说说我都使用了哪些办法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' => "http://static-twirlingvr.oss-cn-hangzhou.aliyuncs.com/yun/voice.wav",
            '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;
    }
    
    ?>
    

    相关文章

      网友评论

          本文标题:微信订阅号语音识别功能的开发

          本文链接:https://www.haomeiwen.com/subject/uyufzttx.html