作者 何书鹏
1 个管道 的构建 通过 耗费 0 秒

语音转文字

@@ -364,8 +364,16 @@ class Almighty extends Api @@ -364,8 +364,16 @@ class Almighty extends Api
364 public function getText() 364 public function getText()
365 { 365 {
366 $filename = $this->request->param('filename'); 366 $filename = $this->request->param('filename');
367 - $res = $this->mp3ToPcm($filename);  
368 - $this->success('成功'); 367 + empty($filename) && $this->error('请输入音频地址');
  368 + $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
  369 + if (!in_array($suffix, ['pcm', 'wav', 'amr', 'm4a', 'mp3'])) {
  370 + $this->error('不支持该音频格式');
  371 + }
  372 + if($suffix == 'mp3'){
  373 + $filename = $this->mp3ToPcm($filename);
  374 + }
  375 + $result = $this->asrJson($filename);
  376 + $this->success('成功',['text'=>$result]);
369 } 377 }
370 378
371 /** 379 /**
@@ -488,14 +496,12 @@ class Almighty extends Api @@ -488,14 +496,12 @@ class Almighty extends Api
488 } 496 }
489 497
490 /** 498 /**
491 - * 上传接口 499 + * mp3转pcm
  500 + * @ApiInternal
492 */ 501 */
493 public function mp3ToPcm($filename) 502 public function mp3ToPcm($filename)
494 { 503 {
495 $key = ltrim($filename,'/'); 504 $key = ltrim($filename,'/');
496 - if(pathinfo($key,PATHINFO_EXTENSION) != 'mp3'){  
497 - return false;  
498 - }  
499 $config = get_addon_config('qiniu'); 505 $config = get_addon_config('qiniu');
500 $auth = new Auth($config['app_key'], $config['secret_key']); 506 $auth = new Auth($config['app_key'], $config['secret_key']);
501 //设置转码参数 507 //设置转码参数
@@ -508,7 +514,8 @@ class Almighty extends Api @@ -508,7 +514,8 @@ class Almighty extends Api
508 $fops = $fops.'|saveas/'.$saveas_key; 514 $fops = $fops.'|saveas/'.$saveas_key;
509 515
510 $policy = array( 516 $policy = array(
511 - 'persistentOps' => $fops 517 + 'persistentOps' => $fops,
  518 + 'persistentNotifyUrl' => $this->request->root(true) . '/mobile/notify/notifyQiniu',
512 ); 519 );
513 $token = $auth->uploadToken($config['bucket'], null, $config['expire'], $policy); 520 $token = $auth->uploadToken($config['bucket'], null, $config['expire'], $policy);
514 $multipart = [ 521 $multipart = [
@@ -524,13 +531,139 @@ class Almighty extends Api @@ -524,13 +531,139 @@ class Almighty extends Api
524 $res = $client->request('POST', $config['uploadurl'], [ 531 $res = $client->request('POST', $config['uploadurl'], [
525 'multipart' => $multipart 532 'multipart' => $multipart
526 ]); 533 ]);
527 - // halt($res);  
528 $code = $res->getStatusCode(); 534 $code = $res->getStatusCode();
529 - halt($code);  
530 //成功不做任何操作 535 //成功不做任何操作
531 } catch (\GuzzleHttp\Exception\ClientException $e) { 536 } catch (\GuzzleHttp\Exception\ClientException $e) {
532 - return false; 537 + $this->error("上传失败");
  538 + }
  539 + return '/' . $filename . '.pcm';
  540 + }
  541 +
  542 + /**
  543 + * 语音转文字
  544 + * @ApiInternal
  545 + */
  546 + public function asrJson($filename){
  547 + define('DEMO_CURL_VERBOSE', false); // 打印curl debug信息
  548 +
  549 + # 填写网页上申请的appkey 如 $apiKey="g8eBUMSokVB1BHGmgxxxxxx"
  550 + $API_KEY = "kVcnfD9iW2XVZSMaLMrtLYIz";
  551 +
  552 + # 填写网页上申请的APP SECRET 如 $secretKey="94dc99566550d87f8fa8ece112xxxxx"
  553 + $SECRET_KEY = "O9o1O213UgG5LFn0bDGNtoRN3VWl2du6";
  554 +
  555 + # 需要识别的文件
  556 + $AUDIO_FILE = $filename;
  557 + # 文件格式
  558 +
  559 + $FORMAT = substr($AUDIO_FILE, -3); // 文件后缀 pcm/wav/amr 格式 极速版额外支持m4a 格式
  560 +
  561 + $CUID = "123456PHP";
  562 + # 采样率
  563 + $RATE = 16000; // 固定值
  564 +
  565 + # 普通版
  566 + $ASR_URL = "http://vop.baidu.com/server_api";
  567 + # 根据文档填写PID,选择语言及识别模型
  568 + $DEV_PID = 1537; // 1537 表示识别普通话,使用输入法模型。
  569 + $SCOPE = 'audio_voice_assistant_get'; // 有此scope表示有语音识别普通版能力,没有请在网页里开通语音识别能力
  570 +
  571 + #测试自训练平台需要打开以下信息, 自训练平台模型上线后,您会看见 第二步:“”获取专属模型参数pid:8001,modelid:1234”,按照这个信息获取 dev_pid=8001,lm_id=1234
  572 + //$DEV_PID = 8001 ;
  573 + //$LM_ID = 1234 ;
  574 +
  575 + # 极速版需要打开以下信息 打开注释的话请填写自己申请的appkey appSecret ,并在网页中开通极速版(开通后可能会收费)
  576 + //$ASR_URL = "http://vop.baidu.com/pro_api";
  577 + //$DEV_PID = 80001;
  578 + //$SCOPE = 'brain_enhanced_asr'; // 有此scope表示有极速版能力,没有请在网页里开通极速版
  579 +
  580 + $SCOPE = false; // 部分历史应用没有加入scope,设为false忽略检查
  581 +
  582 + /** 公共模块获取token开始 */
  583 +
  584 +
  585 + $auth_url = "http://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=".$API_KEY."&client_secret=".$SECRET_KEY;
  586 + $ch = curl_init();
  587 + curl_setopt($ch, CURLOPT_URL, $auth_url);
  588 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  589 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  590 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
  591 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 检查证书中是否设置域名,0不验证
  592 + curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
  593 + $res = curl_exec($ch);
  594 + if(curl_errno($ch))
  595 + {
  596 + $this->error(curl_error($ch));
  597 + }
  598 + curl_close($ch);
  599 +
  600 + echo "Token URL response is " . $res . "\n";
  601 + $response = json_decode($res, true);
  602 +
  603 + if (!isset($response['access_token'])){
  604 + echo "ERROR TO OBTAIN TOKEN\n";
  605 + exit(1);
  606 + }
  607 + if (!isset($response['scope'])){
  608 + echo "ERROR TO OBTAIN scopes\n";
  609 + exit(2);
  610 + }
  611 +
  612 + if ($SCOPE && !in_array($SCOPE, explode(" ", $response['scope']))){
  613 + echo "CHECK SCOPE ERROR\n";
  614 + // 请至网页上应用内开通语音识别权限
  615 + exit(3);
  616 + }
  617 +
  618 + $token = $response['access_token'];
  619 + /** 公共模块获取token结束 */
  620 +
  621 + /** 拼接参数开始 **/
  622 + $audio = file_get_contents($AUDIO_FILE);
  623 + $base_data = base64_encode($audio);
  624 + $params = array(
  625 + "dev_pid" => $DEV_PID,
  626 + //"lm_id" => $LM_ID, //测试自训练平台开启此项
  627 + "format" => $FORMAT,
  628 + "rate" => $RATE,
  629 + "token" => $token,
  630 + "cuid"=> $CUID,
  631 + "speech" => $base_data,
  632 + "len" => strlen($audio),
  633 + "channel" => 1,
  634 + );
  635 +
  636 + $json_array = json_encode($params);
  637 + $headers[] = "Content-Length: ".strlen($json_array);
  638 + $headers[] = 'Content-Type: application/json; charset=utf-8';
  639 +
  640 + /** 拼接参数结束 **/
  641 +
  642 + /** asr 请求开始 **/
  643 +
  644 + $ch = curl_init();
  645 + curl_setopt($ch, CURLOPT_URL, $ASR_URL);
  646 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  647 + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  648 + curl_setopt($ch, CURLOPT_POST, true);
  649 + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
  650 + curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 识别时长不超过原始音频
  651 + curl_setopt($ch, CURLOPT_POSTFIELDS, $json_array);
  652 + curl_setopt($ch, CURLOPT_VERBOSE, DEMO_CURL_VERBOSE);
  653 + $res = curl_exec($ch);
  654 + if(curl_errno($ch))
  655 + {
  656 + $this->error(curl_error($ch));
  657 + }
  658 + curl_close($ch);
  659 +
  660 + // 解析结果
  661 + $response = json_decode($res, true);
  662 +
  663 + if (isset($response['err_no']) && $response['err_no'] == 0){
  664 + return $response['result'][0];
  665 + }else{
  666 + $this->error($response['err_msg']);
533 } 667 }
534 - return $code;  
535 } 668 }
536 } 669 }
@@ -8,7 +8,7 @@ use app\mobile\model\SecretOrder; @@ -8,7 +8,7 @@ use app\mobile\model\SecretOrder;
8 use app\mobile\model\ScoreOrder; 8 use app\mobile\model\ScoreOrder;
9 9
10 /** 10 /**
11 - * 支付异步接口 11 + * 异步接口
12 * @ApiInternal 12 * @ApiInternal
13 */ 13 */
14 class Notify extends Api 14 class Notify extends Api
@@ -100,4 +100,47 @@ class Notify extends Api @@ -100,4 +100,47 @@ class Notify extends Api
100 } 100 }
101 echo $pay->success(); 101 echo $pay->success();
102 } 102 }
  103 +
  104 + /**
  105 + * 七牛云通知回调
  106 + * @ApiInternal
  107 + */
  108 + public function notifyQiniu()
  109 + {
  110 + $config = get_addon_config('qiniu');
  111 + $auth = new Auth($config['app_key'], $config['secret_key']);
  112 + $contentType = 'application/x-www-form-urlencoded';
  113 + $authorization = isset($_SERVER['HTTP_AUTHORIZATION']) ? $_SERVER['HTTP_AUTHORIZATION'] : '';
  114 + if (!$authorization && function_exists('apache_request_headers')) {
  115 + $headers = apache_request_headers();
  116 + $authorization = isset($headers['Authorization']) ? $headers['Authorization'] : '';
  117 + }
  118 +
  119 + $url = $this->request->root(true) . '/mobile/notify/notifyQiniu';
  120 + $body = file_get_contents('php://input');
  121 + $ret = $auth->verifyCallback($contentType, $authorization, $url, $body);
  122 + if ($ret) {
  123 + parse_str($body, $arr);
  124 + $admin_id = isset($arr['admin']) ? $arr['admin'] : 0;
  125 + $user_id = isset($arr['user']) ? $arr['user'] : 0;
  126 + $imageInfo = json_decode($arr['imageInfo'], true);
  127 + $params = array(
  128 + 'admin_id' => (int)$admin_id,
  129 + 'user_id' => (int)$user_id,
  130 + 'filesize' => $arr['filesize'],
  131 + 'imagewidth' => isset($imageInfo['width']) ? $imageInfo['width'] : 0,
  132 + 'imageheight' => isset($imageInfo['height']) ? $imageInfo['height'] : 0,
  133 + 'imagetype' => isset($imageInfo['format']) ? $imageInfo['format'] : '',
  134 + 'imageframes' => 1,
  135 + 'mimetype' => "image/" . (isset($imageInfo['format']) ? $imageInfo['format'] : ''),
  136 + 'extparam' => '',
  137 + 'url' => '/' . $arr['key'],
  138 + 'uploadtime' => time(),
  139 + 'storage' => 'qiniu'
  140 + );
  141 + Attachment::create($params);
  142 + return json(['ret' => 'success', 'code' => 1, 'data' => ['url' => $params['url']]]);
  143 + }
  144 + return json(['ret' => 'failed']);
  145 + }
103 } 146 }