PHP实现讯飞语音转写demo

讯飞语音转写demo,模仿讯飞平台官网python代码


前前后后改了好久,做个记录,以及经历的一些坑。上传切片功能没有,也就是说我这里的切片为1,里面很多bug,异常处理都没有,后面再修改。

经历的坑

1.预处理处的签名处理,因为和python有些函数不一样,所有琢磨了好久。我的php版本是5.5。

python中的写法如下:

ts = str(int(time.time()))
m2 = hashlib.md5()
m2.update((appid + ts).encode('utf-8'))
md5 = m2.hexdigest()
md5 = bytes(md5, encoding='utf-8')
signa = hmac.new(secret_key.encode('utf-8'), md5, hashlib.sha1).digest()
signa = base64.b64encode(signa)
signa = str(signa, 'utf-8')

在php中的写法:其中hash_hmac(),借鉴了一篇博客(https://blog.csdn.net/Ligongxiang123/article/details/76590196),说了两者(php和python)怎么转换。

$ts=time();
$md5 = md5($appid.$ts);
$signa = hash_hmac('sha1',$md5,$secret_key,true);
$signa=base64_encode($signa);

其中在字节数组地方卡住了,查了一下,原因是php5.5中的 string 本来就是“字节串”。为了测试每一步的结果,调试的时候是获取的时间戳固定,两边逐步运行对比出来的。我觉得这可能是讯飞的一个小bug,如果我将传入的时间戳固定,签名也固定,是不是就可以直接过滤掉这一段了!
2.在upload时卡了好几个小时,因为老是报26600(转写业务通用错误)的错误,我当时读取文件用的代码是

$content = urlencode(base64_encode(file_get_contents($upload_file_path)));

但是怎么都不对,改编码也没改对!最后在一篇博客(https://blog.csdn.net/wb_json/article/details/95050959)上看到了解决办法,这个老哥实现了语音转写也提供了代码,但是需要在yii上运行。下面是我复制过来的。

 $mime = (new \finfo(FILEINFO_MIME_TYPE))->file($result->file);
 $curlFile = curl_file_create(
            $file,
            $mime,
            pathinfo(
                $file,
                PATHINFO_BASENAME
            )
);

我没有finfo这个类,最后百度百度,需要安装php_fileinfo扩展,然后用finfo_open().,最终解决问题。

$finfo   = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $upload_file_path);
        finfo_close($finfo);
        $curlFile = curl_file_create(
            $upload_file_path,
            $mime,
            pathinfo(
                $upload_file_path,
                PATHINFO_BASENAME
            )
        );

剩下的就剩json数据格式的问题了,这个百度百度就有了。可以参考(https://www.cnblogs.com/totian/p/7498742.html),下面代码记得改完app_id,secret_key,file_path就可以用了。嗯,应该可以的,我试过。哈哈哈!

代码

<?php
header("Content-Type: text/html; charset=utf-8");
class Sliceidgenerator{
    private $__ch;
    public function __construct() {
            $this->__ch = 'aaaaaaaaa`';
        }
    public function getNextSliceId(){
        $ch = $this->__ch;
        $j = strlen($ch) - 1;
        while($j >= 0){
            $cj = $ch[$j];
            if ($cj != 'z'){
                $ch = substr($ch,0,$j) . chr((ord($cj) + 1)) . substr($ch,$j + 1);
                break;
            }   
            else{
                $ch = substr($ch,0,$j) . 'a' . substr($ch,$j + 1);
                $j = $j - 1;
            }
        }      
        $this->__ch = $ch;
        return $ch;
    }
        
}

class Fx_Api{
	private $lfasr_host = 'http://raasr.xfyun.cn/api';

    # 请求的接口名
    private $api_prepare = '/prepare';
    private $api_upload = '/upload';
    private $api_merge = '/merge';
    private $api_get_progress = '/getProgress';
    private $api_get_result = '/getResult';
    # 文件分片大小10M
    private $file_piece_sice = 10485760;
    # 转写类型
    private $lfasr_type = 0;
    # 是否开启分词
    private $has_participle = 'false';
    private $has_seperate = 'true';
    # 多候选词个数
    private $max_alternatives = 0;
    # 子用户标识
    private $suid = '';
    private $appid;
    private $secret_key;
    private $upload_file_path;
    private $obj;
    private $data;
    private $sig;
    public function __construct($file_path,$appid,$secret_key,$sig) {
        $this->upload_file_path = $file_path;
        $this->appid = $appid;
        $this->secret_key = $secret_key;
        $this->sig = $sig;
    }
 
 	#主要运行函数
    public function run() {
        if($this->upload_file_path!=''){
        	#预处理
            $pre_result = json_decode($this->prepare_request(),true);
            $taskid = $pre_result['data'];
            #上传文件
            $this->upload_request($taskid,$this->upload_file_path);
            $this->merge_request($taskid);

            while (true) {
                $progress = $this->get_progress_request($taskid);
                $progress_dic = json_decode($progress);
                if ($progress_dic->err_no != 0 && $progress_dic->err_no != 26605){
                    return;
                }else{
                    $data = $progress_dic->data;
                    $task_status = json_decode($data);
                    if ($task_status->status == 9){
                        echo('The task ' . $taskid . ' is in processing, task status: ' . $task_status->desc);
                        echo "<br />";
                        break;
                    }
                    echo('The task ' . $taskid . ' is in processing, task status: ' . $task_status->desc);
                    echo "<br />";
                    sleep(0.5);
                }
                    
            }

            $data_all=$this->get_result_request($taskid=$taskid);
            $data_all = json_decode($data_all)->data;
            $data_all=json_decode($data_all);
            $message='';
            for ($i=0;$i<count($data_all);$i++){
                $message.=$data_all[$i]->onebest;
            }      
            $this->data=$message;
        }
    }
 
    public function get_data() {
        return $this->data;
    }

    public function gene_params($apiname,$taskid="",$slice_id=""){
        $appid = $this->appid;
        $secret_key = $this->secret_key;
        $upload_file_path = $this->upload_file_path;
        $ts=time();
        $md5 = md5($appid.$ts);
        $signa = hash_hmac('sha1',$md5,$secret_key,true);
        $signa=base64_encode($signa);
        $file_len = filesize($this->upload_file_path);
        $file_name = basename($this->upload_file_path);
        if($apiname== $this->api_prepare){
            $slice_num = 1;
            $param_dict['app_id'] = $appid;
            $param_dict['signa'] = $signa;
            $param_dict['ts'] = $ts;
            $param_dict['file_len'] = (string)($file_len);
            $param_dict['file_name'] = $file_name;
            $param_dict['slice_num'] = (string)($slice_num);
        }elseif($apiname== $this->api_upload){
            $param_dict['app_id'] = $appid;
            $param_dict['signa'] = $signa;
            $param_dict['ts'] = $ts;
            $param_dict['task_id'] = $taskid;
            $param_dict['slice_id'] = $slice_id;
        }elseif($apiname == $this->api_merge){
            $param_dict['app_id'] = $appid;
            $param_dict['signa'] = $signa;
            $param_dict['ts'] = $ts;
            $param_dict['task_id'] = $taskid;
            $param_dict['file_name'] = $file_name;
        }elseif($apiname == $this->api_get_progress || $apiname == $this->api_get_result){
            $param_dict['app_id'] = $appid;
            $param_dict['signa'] = $signa;
            $param_dict['ts'] = $ts;
            $param_dict['task_id'] = $taskid;
        }
        return $param_dict;
    }

    public function gene_request($apiname, $data, $files='', $headers=''){
        if($files!=''){
            $data['content'] =$files['content'];
        }
        $jsonStr =$data;
        if($apiname==$this->api_prepare||$apiname==$this->api_merge||$apiname==$this->api_get_progress||$apiname==$this->api_get_result){
            $header= array(
                "Content-Type"=>"application/x-www-form-urlencoded;charset=UTF-8",
            );
        }
        if($apiname==$this->api_upload){
            $header = array(
                "Content-Type"=>"multipart/form-data;",
            );
        }
        $url = $this->lfasr_host . $apiname;
        $rt=$this->http_post_json($url, $jsonStr, $header);
        $result = json_decode($rt[1],true);
        if ($result["ok"] == 0){
            echo("success:".$apiname);
            echo "<br />";
            return $rt[1];
        }else{
            return $rt[1];
        } 
    }
    # 预处理gene_request
    public function prepare_request(){
         return $this->gene_request($apiname=$this->api_prepare,
                                 $data=$this->gene_params($this->api_prepare));
    }
    #上传
    public function upload_request($taskid, $upload_file_path){
        $finfo    = finfo_open(FILEINFO_MIME_TYPE);
        $mime = finfo_file($finfo, $upload_file_path);
        finfo_close($finfo);
        $curlFile = curl_file_create(
            $upload_file_path,
            $mime,
            pathinfo(
                $upload_file_path,
                PATHINFO_BASENAME
            )
        );
        $files["filename"] = $this->gene_params($this->api_upload)["slice_id"];
        $files["content"] = $curlFile;
        $response = $this->gene_request($this->api_upload,
                                 $data=$this->gene_params($this->api_upload, $taskid=$taskid,$slice_id=$this->sig->getNextSliceId()),$files=$files);
        return $response;
    }

    public  function merge_request($taskid){
        return $this->gene_request($this->api_merge, $data=$this->gene_params($this->api_merge, $taskid=$taskid));
    }

    # 获取进度
    public  function get_progress_request($taskid){
        return $this->gene_request($this->api_get_progress, $data=$this->gene_params($this->api_get_progress, $taskid=$taskid));
    }
    
    # 获取结果
    public  function get_result_request($taskid){
        $result=$this->gene_request($this->api_get_result, $data=$this->gene_params($this->api_get_result, $taskid=$taskid));
        return $result;
    }
    
    #请求
    public  function http_post_json($url, $jsonStr,$header)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonStr);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return array($httpCode, $response);
    }
}
$sig = new Sliceidgenerator();
$app_id = 'xxxx';
$secret_key = 'xxxxx';
$file_path = 'D:\WWW\tp5\public\audio\10s.wav';
$api = new Fx_Api($file_path,$app_id,$secret_key,$sig);
$api->run();
print_r("转写结果:");
print_r($api->get_data());

运行结果如下图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/i_laolarou/article/details/100024674
今日推荐