Java通過SWIG調用科大訊飛語音SDK實現離線命令詞識別


前言

項目要求在離線環境下實現基本的命令詞識別,並且需要接入后台進行命令詞意圖識別,而后台使用Java編寫,簡單來說就是Java平台下的中文離線語音識別。剛開始調研時我試用了Sphinx4[1],但是效果一般,然后我把目光轉向國內的語音識別平台如科大訊飛[2]。科大訊飛的功能還算齊全,但最大的問題就是離線語音識別不支持Java平台,只有C/C++版本。所以我需要實現一個Java與C進行通信的接口。Java調用C函數最普遍的方法可能是JNI(Java Native Interface)。然而我認為這個方法過於復雜,需要自己定義接口。還有其他方法如JNA[3](Java Native Access),然而我嘗試后均以失敗告終,最后我嘗試了SWIG[4]。SWIG是個幫助使用C或者C++編寫的軟件能與其它各種高級編程語言進行嵌入聯接的開發工具,簡單高效滿足需求。

正文

方案選擇

Java+SWIG+科大訊飛,平台為Ubuntu 17.04

准備工作

  1. 從訊飛開放平台下載離線命令詞識別SDK,得到以下文件

  2. 根據doc文件夾下的MSC_Novice_Manual_for_Linux.pdf建立一個demo工程,確認樣例運行沒有問題

  3. 從網上下載SWIG的安裝包或者使用Ubuntu自帶apt-get獲取SWIG。sudo apt install swig

STEP1

創建鏈接文件如asr.i,文件中定義接口
vim asr.i

/* File: asr.i */
%module asr
%{
int main();
%}
int main();

並使用SWIG輸出asr.java,asrJNI.java和asr_wrap.c
swig swig -java asr.i
注意:如果你需要將此文件定義在一個包中如util那么此命令應加上-package參數
swig -java -package util.asr asr.i

STEP2

編譯所有.c文件包括剛才生成的asr_wrap.c。
注意:編譯asr_wrap.c時需要頭文件jni.h和jni_md.h。這兩個頭文件可以在Java環境安裝目錄下找到,我的路徑為
/usr/lib/jvm/java-1.8.0-openjdk-amd64/include/
/usr/lib/jvm/java-1.8.0-openjdk-amd64/include/linux
使用gcc命令分別編譯
gcc -fPIC -c asr_wrap.c -I/usr/lib/jvm/java-1.8.0-openjdk-amd64/include/ -I/usr/lib/jvm/java-1.8.0-openjdk-amd64/include/linux
gcc -fPIC -c -I../include asr_record_sample.c -o asr_sample.o
使用ld命令鏈接所有.o文件
ld -G -I../include asr_wrap.o asr_sample.o -o ../libs/x64/libasr.so -L../libs/x64 -lmsc -lrt -ldl -lpthread -lasound
最后得到libasr.so文件

STEP3

編寫簡單的Java程序進行測試
vim run.java

/*run.java*/
public class run {
  static {
    System.loadLibrary("asr");
  }
  public static void main(String argv[]) {
    asr.main();
  }
}

編譯並運行Java程序
javac *.java
java run

結語

整個過程發現除了編譯的部分繁瑣了些,其他實現還是比較容易,通過SWIG實現Java和C之間的通訊是一個比較可行的解決方案。

Reference

  1. OPEN SOURCE SPEECH RECOGNITION TOOLKIT
  2. 訊飛開放平台
  3. Java通過JNA調用科大訊飛語音雲實現語音識別功能
  4. Simplified Wrapper and Interface Generator
  5. SWIG and Java


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM