前文已经成功使用 kaldi 将模型训练好并解码测试,现在我们借助 vosk-api 来让模型在 Android 手机上跑起来吧!
所用项目
kaldi-android-demo,一个 kaldi 模型在 android 运行的 demo,作者还提供了些预训练的模型,如果不需要使用自己训练的模型的话,或者没有太多修改的话,借鉴这个 demo 足以使大多 kaldi 模型在 android 上运行测试起来。
由于我们需要使用自己训练的模型,所以我们必须对 aar 做些定制化,也就需要修改 vosk-api 项目,它会帮助我们将 kaldi 编译成 aar 使之能在 arm 平台上运行。
使用
首先将 vosk-api 项目 pull 下来,对于 android 平台 aar 的生成,只需要进入项目 android
目录然后使用 gradle 编译即可。
1 | cd android |
如果有缺少
ANDROID_SDK_HOME
、ANDROID_NDK_HOME
环境之类的报错,还请根据报错信息配置后再重试。
这个编译过程会非常的耗时,因为编译命令首先会执行 android/build-kaldi.sh
脚本,而这个脚本会把整个 kaldi 下载下来并编译。每次编译 aar 都会重复相同步骤,未免浪费资源,可以将 android/build-kaldi.sh
脚本中每个步骤做分割,按 kaldi 项目的风格,增加 stage 控制,之后再编译时,先手动修改 stage, 越过不需要执行的步骤。如果后面修改了 kaldi 源码,也一般只需要额外编译所属模块即可。像这样:
1 | if [ $stage -le 7 ]; then |
build-kaldi.sh
执行完后,gradle 会执行 task swig,使用 swig 工具将 src
目录下的文件转为 java 并生成 JNI。所以,如果要想对模型和逻辑做些定制化,就要从 src 目录下的这几个文件入手:
1 | json.h kaldi_recognizer.cc kaldi_recognizer.h model.cc model.h spk_model.cc spk_model.h vosk.i |
这里我只是稍微改了下 model.cc,修改 feature_info_.use_ivectors
使之能够运行没有 ivector 特征的模型。
kaldi-android-demo所提供的模型 fst 是 LookAhead decoding fst
,其实代码里也支持普通的 HCLG.fst:
1 | hclg_fst_rxfilename_ = model_path_str + "/HCLG.fst"; |
其他琐碎经验:
- 如果你像我一样不需要使用项目中的 SpeechRecognizer 而是想要完全定制 AudioRecord 输入源,可以将 build.gradle 中,
java.srcDirs
部分的src/main/java
注释掉。
解码测试
在你的项目中加入编译生成的 aar 以及之前的模型文件(哪些模型文件是必要的可以参考 src/model.cc
代码中 各个 _rxfilename
后缀变量),使用整个模型文件的目录构建 org.kaldi.Model
和 org.kaldi.KaldiRecognizer
,然后就可以不断向 KaldiRecognizer 喂音频数据并得到结果了,具体实现参考 vosk-api 项目中的 android\src\main\java\org\kaldi\SpeechRecognizer.java
以及 kaldi-android-demo 的实现细节。