1. gzyueqian
      13352868059

      嵌入式linux系統語音識別程序就是這么簡單

      更新時間: 2018-11-05 14:58:38來源: 嵌入式培訓瀏覽量:7402

          linux語音識別技術對于一些熟練掌握的人而言是很有意思的,但是對于一些對這方面苦惱的人來說,linux語音識別毫無樂趣而言,而對于我這久經沙場的人來說,linux語音識別程序是很容易的,在這里分享一些linux語音識別程序的詳細步驟,對這方面有迷惑的人,讓你加快學習的速度。

          我之前在學習的時候做過一個貪吃蛇小游戲,本來打算想把這個游戲弄成語音控制的,在我工作了以后一直也沒有時間,就在幾天前,應一位小學弟的要求,今天就用這個小游戲來舉例,讓你學會linux語音識別。


          剛開始你需要去下載一個SDK-linux,需要注冊先。。。在下載下來的include文件夾下,有四個文件:msp_errors.hmsp_types.hqisr.hqtts.h。這四個文件前面的兩個是通用的數據結構,而后面的一個是語音識別用的頭文件,一個是語音合成用的頭文件,因為我就需要語音識別的功能,只要在我的代碼中include進qisr.h頭文件就OK啦。在bin文件夾下比較亂,但主要就是libmsc.so和libspeex.so兩個動態庫,我直接把這兩個動態庫拷到/usr/lib里面。

          在bin文件夾下注意到一個asr_keywords_utf8.txt的文件,這個SDK的你需要知道思路:你把你想識別的文字寫到asr_keywords_utf8.txt中,接下來上傳到服務器上,然后返回一個GrammarID,據說上傳一次“終身有效”,意思就是不讓重復上傳占用服務器空間,反正有了這個GrammarID以后在不同的程序中想識別相同的文字就直接用好了,比如我想識別“左,右,上,下,圖書館,獨自”,把這些漢字寫到asr_keywords_utf8.txt中,而且必須是utf-8的格式,當然在linux下默認如此。下面展示一下我寫的上傳這個txt并獲得GrammarID的代碼:


      #include
      
      #include
      
      #include
      
      #include
      
      #include
      
      #define TRUE 1
      
      #define FALSE 0
      
      int main()
      
      {
      
      int ret = QISRInit("appid=xxxxxxx");
      
      if(ret != MSP_SUCCESS)
      
      {
      
      printf("QISRInit with errorCode: %d n", ret);
      
      return 0;
      
      }
      
      char GrammarID[128];
      
      memset(GrammarID, 0, sizeof(GrammarID));
      
      const int MAX_KEYWORD_LEN = 4096;
      
      ret = MSP_SUCCESS;
      
      const char * sessionID = NULL;
      
      sessionID = QISRSessionBegin(NULL, "ssm=1,sub=asr", &ret);
      
      if(ret != MSP_SUCCESS)
      
      {
      
      printf("QISRSessionBegin with errorCode: %d n", ret);
      
      return ret;
      
      }
      
      char UserData[MAX_KEYWORD_LEN];
      
      memset(UserData, 0, MAX_KEYWORD_LEN);
      
      FILE* fp = fopen("asr_keywords_utf8.txt", "rb");
      
      if (fp == NULL)
      
      {
      
      printf("keyword file cannot openn");
      
      return -1;
      
      }
      
      unsigned int len = (unsigned int)fread(UserData, 1, MAX_KEYWORD_LEN, fp);
      
      UserData[len] = 0;
      
      fclose(fp);
      
      const char* testID = QISRUploadData(sessionID, "contact", UserData, len, "dtt=keylist", &ret);
      
      if(ret != MSP_SUCCESS)
      
      {
      
      printf("QISRUploadData with errorCode: %d n", ret);
      
      return ret;
      
      }
      
      memcpy((void*)GrammarID, testID, strlen(testID));
      
      printf("GrammarID: "%s" n", GrammarID);
      
      QISRSessionEnd(sessionID, "normal");
      
      return 0;
      
      }
      

          記住要達到這個效果以后,把這些記下來就好了,接下來的一個步驟要好好挺,就是錄制了,在這里有一個點需要注意一下,就是不能直接用ubuntu自帶的錄音機,那樣會識別不了,自帶的錄音軟件都是默認32位采樣,只能用ffmpeg或自己寫代碼錄制,ffmpeg命令如下:

      ffmpeg -f alsa -i hw:0 -ar 16000 -ac 1 lib.wav

          我錄制了2秒音頻,就會有識別代碼:


      #include
      
      #include
      
      #include
      
      #include
      
      #include
      
      #define TRUE 1
      
      #define FALSE 0
      
      int run_asr(const char* asrfile);
      
      const int BUFFER_NUM = 4096;
      
      const int MAX_KEYWORD_LEN = 4096;
      
      int main(int argc, char* argv[])
      
      {
      
      int ret = MSP_SUCCESS;
      
      const char* asrfile ="lib.wav";
      
      ret = QISRInit("appid=xxxxxx");
      
      if(ret != MSP_SUCCESS)
      
      {
      
      printf("QISRInit with errorCode: %d n", ret);
      
      return 0;
      
      }
      
      ret = run_asr(asrfile);
      
      QISRFini();
      
      char key = getchar();
      
      return 0;
      
      }
      
      int run_asr(const char* asrfile)
      
      {
      
      int ret = MSP_SUCCESS;
      
      int i = 0;
      
      FILE* fp = NULL;
      
      char buff[BUFFER_NUM];
      
      unsigned int len;
      
      int status = MSP_AUDIO_SAMPLE_CONTINUE, ep_status = -1, rec_status = -1, rslt_status = -1;
      
      //const char* GrammarID="e7eb1a443ee143d5e7ac52cb794810fe";
      
      const char *GrammarID="c66d4eecd37d4fe1c8274a2224b832d5";
      
      const char* param = "rst=json,sub=asr,ssm=1,aue=speex,auf=audio/L16;rate=16000";//注意sub=asr
      
      const char* sess_id = QISRSessionBegin(GrammarID, param, &ret);
      
      if ( MSP_SUCCESS != ret )
      
      {
      
      printf("QISRSessionBegin err %dn", ret);
      
      return ret;
      
      }
      
      fp = fopen( asrfile , "rb");
      
      if ( NULL == fp )
      
      {
      
      printf("failed to open file,please check the file.n");
      
      QISRSessionEnd(sess_id, "normal");
      
      return -1;
      
      }
      
      printf("writing audio...n");
      
      //
      
      int count=0;
      
      //
      
      while ( !feof(fp) )
      
      {
      
      len = (unsigned int)fread(buff, 1, BUFFER_NUM, fp);
      
      feof(fp) ? status = MSP_AUDIO_SAMPLE_LAST : status = MSP_AUDIO_SAMPLE_CONTINUE;
      
      if(status==MSP_AUDIO_SAMPLE_LAST)
      
      printf("MSP_AUDIO_SAMPLE_LASTn");
      
      if(status==MSP_AUDIO_SAMPLE_CONTINUE)
      
      printf("MSP_AUDIO_SAMPLE_CONTINUEn");
      
      //
      
      ret = QISRAudioWrite(sess_id, buff, len, status, &ep_status, &rec_status);
      
      if ( ret != MSP_SUCCESS )
      
      {
      
      printf("nQISRAudioWrite err %dn", ret);
      
      break;
      
      }
      
      //
      
      printf("%dn",count++);
      
      //
      
      if ( rec_status == MSP_REC_STATUS_SUCCESS )
      
      {
      
      const char* result = QISRGetResult(sess_id, &rslt_status, 0, &ret);
      
      if (ret != MSP_SUCCESS )
      
      {
      
      printf("error code: %dn", ret);
      
      break;
      
      }
      
      else if( rslt_status == MSP_REC_STATUS_NO_MATCH )
      
      printf("get result nomatchn");
      
      else
      
      {
      
      if ( result != NULL )
      
      printf("get result[%d/%d]:len:%dn %sn", ret, rslt_status,strlen(result), result);
      
      }
      
      }
      
      printf(".");
      
      }
      
      printf("n");
      
      if (ret == MSP_SUCCESS)
      
      {
      
      printf("get reuslt~~~~~~~n");
      
      char asr_result[1024] = "";
      
      unsigned int pos_of_result = 0;
      
      int loop_count = 0;
      
      do
      
      {
      
      const char* result = QISRGetResult(sess_id, &rslt_status, 0, &ret);
      
      if ( ret != 0 )
      
      {
      
      printf("QISRGetResult err %dn", ret);
      
      break;
      
      }
      
      if( rslt_status == MSP_REC_STATUS_NO_MATCH )
      
      {
      
      printf("get result nomatchn");
      
      }
      
      else if ( result != NULL )
      
      {
      
      //
      
      FILE*f=fopen("data.txt","wb");
      
      printf("~~~%dn",strlen(result));
      
      fwrite(result,1,strlen(result),f);
      
      fclose(f);
      
      //
      
      printf("[%d]:get result[%d/%d]: %sn", (loop_count), ret, rslt_status, result);
      
      strcpy(asr_result+pos_of_result,result);
      
      pos_of_result += (unsigned int)strlen(result);
      
      }
      
      else
      
      {
      
      printf("[%d]:get result[%d/%d]n",(loop_count), ret, rslt_status);
      
      }
      
      usleep(500000);
      
      } while (rslt_status != MSP_REC_STATUS_COMPLETE && loop_count++ < 30);
      
      if (strcmp(asr_result,"")==0)
      
      {
      
      printf("no resultn");
      
      }
      
      }
      
      QISRSessionEnd(sess_id, NULL);
      
      printf("QISRSessionEnd.n");
      
      fclose(fp);
      
      return 0;
      
      }
      

          識別后,你就會看到輸出結果如下:



      kl@kl-Latitude:~/xunfeiSDK$ ./a.out
      writing audio...
      MSP_AUDIO_SAMPLE_CONTINUE
      0
      .MSP_AUDIO_SAMPLE_CONTINUE
      1
      .MSP_AUDIO_SAMPLE_CONTINUE
      2
      .MSP_AUDIO_SAMPLE_CONTINUE
      3
      .MSP_AUDIO_SAMPLE_CONTINUE
      4
      .MSP_AUDIO_SAMPLE_CONTINUE
      5
      .MSP_AUDIO_SAMPLE_CONTINUE
      6
      .MSP_AUDIO_SAMPLE_CONTINUE
      7
      .MSP_AUDIO_SAMPLE_CONTINUE
      8
      .MSP_AUDIO_SAMPLE_CONTINUE
      9
      .MSP_AUDIO_SAMPLE_CONTINUE
      10
      .MSP_AUDIO_SAMPLE_CONTINUE 
      11
      .MSP_AUDIO_SAMPLE_CONTINUE
      12
      .MSP_AUDIO_SAMPLE_CONTINUE
      13
      .MSP_AUDIO_SAMPLE_CONTINUE
      14
      .MSP_AUDIO_SAMPLE_CONTINUE
      15
      .MSP_AUDIO_SAMPLE_CONTINUE
      16
      .MSP_AUDIO_SAMPLE_CONTINUE
      17  
      .MSP_AUDIO_SAMPLE_CONTINUE
      18
      .MSP_AUDIO_SAMPLE_CONTINUE
      19
      .MSP_AUDIO_SAMPLE_CONTINUE
      20
      .MSP_AUDIO_SAMPLE_CONTINUE
      21
      .MSP_AUDIO_SAMPLE_CONTINUE
      22
      .MSP_AUDIO_SAMPLE_LAST
      23
      .
      get reuslt~~~~~~~
      [0]:get result[0/2]
      ~~~123
      [1]:get result[0/5]: {"sn":1,"ls":true,"bg":0,"ed":0,"ws":[{"bg":0,"cw":[{"sc":"85","gm":"0","w":"圖書館","mn":[{"contact":"圖書館"}]}]}]}
      QISRSessionEnd.
      

          還有一個注意的點這個輸出格式是個坑,因為官方的例子默認是直接輸出識別的結果,但是結果是GB2312格式的,在linux終端下是亂碼,在這里你要注意:在QISRSessionBegin()函數初始化的時候第二個參數param中的rst改成json,就是按照json格式把所有結果全輸出來后,是utf8格式的漢字,之后再用json模塊來解就妥妥的了~整體代碼很清晰。
          1.先要調用QISRInit()函數,參數是自己的appid,每個SDK都是注冊才能下載的,所以是的,用來區分用戶的,不同級別的用戶每天可以使用SDK的次數有限制,畢竟人用的多了語音識別的性能肯定會下降;
          2.之后就是把GrammarID,輸入輸出的參數param和調用狀態返回值ret作為參數傳入QISRSessionBegin()函數中進行初始化,返回值是sessionID,這個是后面所有函數的主要參數之一;
          3.打開自己的音頻文件,調用QISRAudioWrite()函數寫入,可以分段也可以一次,個參數是sessionID,上面初始化函數返回的值,第二個參數是音頻數據頭指針,第三個參數是音頻文件大小,第四個參數是音頻發送的狀態,表示發送完了沒有,剩下兩個是服務器端檢測語音狀態和識別狀態的返回值;
          4.調用QISRGetResult()函數獲取識別的結果,個參數還是sessionID,第二個參數是輸出識別的狀態,第三個參數是與服務器交互的間隔時間,官方建議5000,我取為0,第四個參數是調用狀態返回值ret,這個函數的返回值就是上面結果的json數據了;
          linux語音識別程序你是不是已經掌握了呢,你可以多看幾遍,先做一個簡單的,接下來有簡到難,明白了其中的道理,那么你就是linux語音識別程序的大神了。

      免費預約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 日韩精品在线观看国产精品 | 中文字幕日本一区 | 亚洲欧美日韩国产综合在线一区 | 永久免费人成在线观看 | 真实国产乱子伦高清对白 | 亚洲伊人a和欧美伊人和a |