基于kaldi的在线语音识别

本文是基于kaldi的在线语音识别,使用b/s架构进行在线识别。适用于刚刚接触的小白。

开发环境:jdk-1.8,Ubuntu16.04,Eclipse。

开发过程:

(1)准备必须的文件

如果你想要实现在线语音识别功能在kaldi下,那么你需要有训练好的“35.mdl、final.mdl、HCLG.fst、words.txt、”这些文件。这些文件分别位于你训练的文件中的   比如 kaldi/egs/cn/s1/exp/*tri1/  和 kaldi/egs/cn/s1/exp/tri1/graph/目录下。(不同的模型,不同的文件)

(2)文件的准备以及代码的修改

在kaldi/tools目录下运行 sudo bash extras/install_portaudio.sh

从kaldi/egs/voxforge/的目录下拷贝出来online_demo文件夹(先运行run.sh (sudo bash run.sh)之后再拷贝)。拷贝到你训练的模型文件夹下。比如kaldi/cn/目录下。创建完成之后,在online_demo/online_data/models/目录下,创建一个文件,比如tir1(三因素的模型),然后将(1)中的四个文件拷贝到tri1中。

将你要识别的音频文件拷贝到online_demo/online_data/audio/目录下。

(3)修改online_demo/run.sh

将这段话改为你的模型的文件夹的名字

# Change this to "tri2a" if you like to test using a ML-trained model
ac_model_type=tri1

将你的模型文件放置进去

online-wav-gmm-decode-faster --verbose=1 --rt-min=0.8 --rt-max=0.85\
            --max-active=4000 --beam=12.0 --acoustic-scale=0.0769 \
            scp:$decode_dir/input.scp $ac_model/final.mdl$ac_model/HCLG.fst \
            $ac_model/words.txt '1:2:3:4:5' ark,t:$decode_dir/trans.txt \
            ark,t:$decode_dir/ali.txt $trans_matrix;;

将以下的代码删掉

if [ ! -s ${data_file}.tar.bz2 ]; then
    echo "Downloading test models and data ..."
    wget -T 10 -t 3 $data_url;

    if [ ! -s ${data_file}.tar.bz2 ]; then
        echo "Download of $data_file has failed!"
        exit 1
    fi
fi

(4)遇到的问题

可能解码出来的结果不是你想要的句子,那么你需要手动进行“拼接”,因为这里的解码只解码到了  一个词的“ID”,然后生成的是“词的序列”,不是你想要的,那么你就要手动拼接,我写的拼接代码如下,仅供参考,不会的可以再问我。

package com.imut.handlwav;
/**
* Created by IMUT-GB503-韩佳俊
* Date 2017-12-18
* Email [email protected]
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;

public class WavToWord {

public static String Handle(String path) {
String result = null;
//将音频文件拷贝到你所用模型的文件下的在线识别文件的音频文件中
String command="cp "+path+" /home/jiajun/kaldi/egs/cn/online_demo/online-data/audio/";
EcecuteShell(command);
//执行识别命令
command = "bash /home/jiajun/OnlineDecoding/run.sh";
EcecuteShell(command);
//将识别ID组合成序列(词序列)
IDCombine("/home/jiajun/kaldi/egs/cn/online_demo/work/trans.txt","/home/jiajun/kaldi/egs/cn/online_demo/work/ref.txt");
//将ID翻译成句子
IDToWord("/home/jiajun/kaldi/egs/cn/online_demo/work/ref.txt","/home/jiajun/kaldi/egs/cn/online_demo/online-data/models/tri1/words.txt","/home/jiajun/OnlineDecoding/result.txt");
//提取结果内容
result = WithdrawResult("/home/jiajun/OnlineDecoding/result.txt");
//删除拷贝进来的音频文件
command="rm -rf /home/jiajun/kaldi/egs/cn/online_demo/online-data/audio/";
EcecuteShell(command);
//因为上一步的删除也会把文件夹删掉,因为必须有文件夹,所以要再创建一个
command="mkdir /home/jiajun/kaldi/egs/cn/online_demo/online-data/audio/";
EcecuteShell(command);
command="touch /home/jiajun/kaldi/egs/cn/online_demo/online-data/audio/trans.txt";
EcecuteShell(command);
return result;
}
//执行linux下的shell命令
public static void EcecuteShell(String command) {
try {
Process ps = Runtime.getRuntime().exec(command);
ps.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
//提取结果
private static String WithdrawResult(String path) {
StringBuilder result = new StringBuilder();
try {
BufferedReader br = new BufferedReader(new FileReader(path));// 构造一个BufferedReader类来读取文件
String s = null;
while ((s = br.readLine()) != null) {// 使用readLine方法,一次读一行
if(s.equals(""))
continue;
result.append(s);
}
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return result.toString();
}

//把一个音频的ID号(对应单词)组合起来,形成ID序列(句子)
public static void IDCombine(String readPath,String outPath) {
FileOutputStream out = null;
try {
BufferedReader br = new BufferedReader(new FileReader(readPath));// 构造一个BufferedReader类来读取文件
String s = null;
String result="";
out = new FileOutputStream(new File(outPath));
while ((s = br.readLine()) != null) {// 使用readLine方法,一次读一行
String temp[]=s.split(" ");
for(int i=1;i<temp.length;i++) {
result=result+temp[i];
result=result+" ";
}
}
result=result.trim();
out.write(result.getBytes());
br.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//将识别的ID号转换成句子。这个得自己手动写,文件结构为多行,在每一行有两列: ID 对应的单词 ,根据识别的ID号将单词组合起来。
public static void IDToWord(String readPath1,String readPath2,String outPath) {
FileOutputStream out = null;
try {
BufferedReader br = new BufferedReader(new FileReader(readPath1));// 构造一个BufferedReader类来读取文件
String s1 = null;
String result="";
out = new FileOutputStream(new File(outPath));
while ((s1 = br.readLine()) != null) {// 使用readLine方法,一次读一行
String temp[]=s1.split(" ");
for(int i=0;i<temp.length;i++) {
BufferedReader brtemp = new BufferedReader(new FileReader(readPath2));// 构造一个BufferedReader类来读取文件
String stemp = null;
while ((stemp = brtemp.readLine()) != null) {// 使用readLine方法,一次读一行
String wordToId[]=stemp.split(" ");
if(temp[i].equals(wordToId[1])) {
result=result+wordToId[0];
result=result+" ";
}
}
brtemp.close();
}
}
result=result.trim();
out.write(result.getBytes());
br.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(5)注意事项

一定要根据你的据地路径来改,以上的代码均是根据我的路径来改的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章