微信小程序调用讯飞的音频评分接口

第一步在管理端配置请求地址

  wss://ise-api.xfyun.cn

第二步接口鉴权,生成url

由于在小程序端生成的url总是失败,就把url的生成放在了服务端。

   @RequestMapping(value = "/getAuthUrl", method = RequestMethod.GET)
    public  @ResponseBody
    Message  getAuthUrl() throws Exception {

        String  hostUrl="wss://ise-api.xfyun.cn/v2/open-ise",
               host="ise-api.xfyun.cn",
            //在控制台-我的应用-语音评测(流式版)获取
               appid= "************",
            //在控制台-我的应用-语音评测(流式版)获取
               apiSecret= "**************",//在控制台-我的应用-语音评测(流式版)获取
                apiKey= "*************",
                 uri="/v2/open-ise";
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        String date = format.format(new Date());

        StringBuilder builder = new StringBuilder("host: ").append(host).append("\n").//
            append("date: ").append(date).append("\n").//
            append("GET ").append(uri).append(" HTTP/1.1");
      
        Charset charset = Charset.forName("UTF-8");
        Mac mac = Mac.getInstance("hmacsha256");
        SecretKeySpec spec = new SecretKeySpec(apiSecret.getBytes(charset), "hmacsha256");
        mac.init(spec);
        byte[] hexDigits = mac.doFinal(builder.toString().getBytes(charset));
        String sha = Base64.getEncoder().encodeToString(hexDigits);

        String authorization = String.format("api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha);


        StringBuffer httpUrl = new StringBuffer();
        httpUrl.append(hostUrl).append("?")
            .append("authorization=").append(Base64.getEncoder().encodeToString(authorization.getBytes(charset)))
            .append("&date=").append(URLEncoder.encode(date,"UTF-8"))
            .append("&host=").append(host);


        return MessageUtil.createSuccessMessage(httpUrl.toString());
    }

第三步 上传MP3文件

生成MP3文件

this.recorderManager = wx.getRecorderManager();
    const options = {
      duration: duration,
      sampleRate: 16000,
      numberOfChannels: 1,
      encodeBitRate: 48000,
      format: 'mp3',
    };
    this.recorderManager.start(options);

  
    this.recorderManager.onStop(res => {
      if (this.playAndRecordStatus == 'record') {
        //生成的临时mp3文件
        this.tempFile = res.tempFilePath;
       
         //可以直接调用上传MP3的问题
         new Promise(r=>{
            this.$emit("record-finished",{text:this.segmentItem.eng,pcmFile:this.tempFile})
         })
       
        this.playRecord();
        this.$apply();
      }
    });

创建socket并上传MP3文件

//上传MP3文件,pcmFile mp3文件的路径,text测评的文本
 checkAudio(pcmFile, text) {
 //把文本中的中文替换掉,如果有中文就会报错
      text = text.replaceAll(/[\u4E00-\u9FA5]/g, '');

   //获取服务端生成的url
    Check.getAuthUrl(wssUrl => {
      console.log(wssUrl);
      //创建socket
      this.socketTask = wx.connectSocket({
        url: wssUrl,
        complete: e => {
          console.log(e);
        }
      });

      this.socketTask.onError(e => {
        console.log('==onError=');
        console.log(e);
        //  this.readFile(pcmFile,0,1280,text)
      });
  
    
      this.socketTask.onOpen(e => {
      //socket 打开后开始上传文件
        const fs = wx.getFileSystemManager();
        fs.getFileInfo({
          filePath: pcmFile,
          complete: e => {
            this.readFileTime(fs, pcmFile, 0, 1280, text, e.size);
          }
        });
      
      });

     //处理socket返回的结果
      this.socketTask.onMessage(e => {
      
        var reslut = JSON.parse(e.data);
        //code!=0 测评出现错误
        if(reslut.code !=0){
            console.log(reslut);
            this.socketTask.close()
          return;
        }
        
        if(reslut&&reslut.data&&reslut.data.status == '2'){
          //测评完成,返回结果
          this.socketTask.close()
          const base64 = new Base64();
          var d = base64.decode(reslut.data.data);
          //处理返回的XML
          this.loadXML(d);
        }
      });
    });
  }

  readFileTime(fs, filePath, startIndex, length, text, lastTotal){
    //设置定时器,每40毫秒上传一次
    var intervalId =  setInterval(()=>{
        this.readFile(
            fs,
            filePath,
            startIndex,
            length,
            text,
            lastTotal
          );
          if(lastTotal<=length){
            clearInterval(intervalId)
            return;
          }
          startIndex =  startIndex + length;
          lastTotal =    lastTotal - length;


    },40)
  }

读取文件并上传

  readFile(fs, filePath, startIndex, length, text, lastTotal) {
 
    var isLast = false;
    if (length >= lastTotal) {
      length = lastTotal;
      isLast = true;
    }
    fs.readFile({
      filePath: filePath,
      position: startIndex,
      length: length,
      complete: e => {
       
      },
      success: e => {
      
        var baseData = wx.arrayBufferToBase64(e.data);

        if (!isLast) {
         
          if (startIndex == 0) {
            this.send(baseData, text, this.FRAME.STATUS_FIRST_FRAME);
          } else {
            if((lastTotal - length)==0){
          
              this.send(baseData, text, this.FRAME.STATUS_LAST_FRAME);
              return;
            }else{
               this.send(baseData, text, this.FRAME.STATUS_CONTINUE_FRAME);
            }
          }

        } else {

          this.send(baseData, text, this.FRAME.STATUS_LAST_FRAME);
        }
      }
    });
    //  var data = fs.readFileSync(filePath,startIndex,length)
  }

上传数据

  // 上传数据
  send(data, text, status) {
    var frame = '';
    switch (status) {
      case this.FRAME.STATUS_FIRST_FRAME:
            
        // 第一次数据发送:
        frame = {
          common: { app_id: this.config.appid },
          business: {
            //  服务类型指定 ise(开放评测)
            sub: 'ise',
            // 中文:cn_vip 英文:en_vip
            ent: 'en_vip',
            // 题型:句子朗读
            category: 'read_sentence',
            // 待评测文本编码 utf-8
            text: '\uFEFF'+text,
            check_type:"easy",
            // 待评测文本编码 utf-8 gbk
            tte: 'utf-8',
            rstcd: 'utf8',
            // 跳过ttp直接使用ssb中的文本进行评测(使用时结合cmd参数查看),默认值true
            ttp_skip: true,
            cmd: 'ssb',
            aue: 'lame',
            auf: 'audio/L16;rate=16000'
          },
          data: { status: 0 }
        };
        this.socketTask.send({
          data: JSON.stringify(frame),
          complete: e => {
          
          }
        });
        // 后续数据发送
        frame = {
          common: { app_id: this.config.appid },
          business: { aus: 1, cmd: 'auw', aue: 'lame' },
          data: { status: 1, data: data }
        };
       
        break;
      case this.FRAME.STATUS_CONTINUE_FRAME:
        
        frame = {
          common: { app_id: this.config.appid },
          business: { aus: 2, cmd: 'auw', aue: 'lame' },
          data: { status: 1, data: data }
        };
        break;
      case this.FRAME.STATUS_LAST_FRAME:
       
        frame = {
          common: { app_id: this.config.appid },
          business: { aus: 4, cmd: 'auw', aue: 'lame' },
          data: { status: 2, data: data }
        };
        break;
    }
   //上传数据
    this.socketTask.send({
      data: JSON.stringify(frame),
      complete: e => {
        console.log(e);
      }
    });
  }

解析xml


  loadXML(xml) {

   //把xml转成json
    var x2js = new X2JS();
    var json = x2js.xml2js(xml);
   
    var chapter = json.xml_result.read_sentence.rec_paper.read_chapter;
    var sentences = chapter.sentence;

    var ttsScore = {};

    ttsScore.totalScore = this.toIntScore(chapter._total_score)

    var words = [];
    if(sentences._total_score){
      words = words.concat(this.getWordList(sentences))
    }else{
      for (var i = 0; i < sentences.length; i++) {
           words = words.concat(this.getWordList(sentences[i]))
      }
    }

   

    ttsScore.wordList = words;
   
     //当前播放的文本拆成一个个的单词
    var wordItemArr = this.currentPlaySegment.wordItemArr

    var j = 0
    //对比返回的单词,和原文本的单词,给原文本的单词设置评分
    for(var i = 0 ; i < wordItemArr.length; i++){
      var wordItem = wordItemArr[i]
      if(j>=words.length){
        break;
      }
      var wordScore = words[j]
      var text = wordItem.text.toLowerCase().replaceAll(/[^a-zA-Z0-9_-]/g, '');
      var word = wordScore.word.toLowerCase().replaceAll(/[^a-zA-Z0-9_-]/g, '');
     
      if(text== word){
        j++
      }else{
        continue
      }


      if(wordScore.score>95){
        wordItemArr[i].score = 1;
      }else  if(wordScore.score>85){
         wordItemArr[i].score = 2;
      }else{
          wordItemArr[i].score = 3;
      }
    }

    

this.currentPlaySegment.totalScore = ttsScore.totalScore
//给原文本的句子设置评分
for(var i = 0 ; i< this.segmentItems.length ; i++){
  if(this.segmentItems[i].start == this.currentPlaySegment.start){
    this.segmentItems[i].totalScore = ttsScore.totalScore
    this.segmentItems[i].wordItemArr=wordItemArr
    break;
  }
}

this.$broadcast("show-score",this.currentPlaySegment)
this.$apply()
  }
  
  //给测评的结果乘20编程百分制
   toIntScore(score){
    return  parseInt(parseFloat(score)*20)
  }

扫码体验

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容