赞
踩
1、离线命令词识别调用主函数
- package com.iflytek;
- import com.iflytek.util.Step2_asr_thread;
- import com.iflytek.util.Step3_audioFormat;
- import java.util.Scanner;
- import javax.sound.sampled.AudioFormat;
- import javax.sound.sampled.AudioSystem;
- import javax.sound.sampled.DataLine;
- import javax.sound.sampled.TargetDataLine;
-
- /**
- * 请注意!!!
- * 1.首先到控制台https://console.xfyun.cn/services/mlcsb下载离线命令词识别的Windows MSC。
- * 2.下载的离线命令词识别Windows MSC解压后,把bin目录下msc文件夹、dll文件、call.bnf文件拷贝到res目录下。
- * 3.最后请替换Step2_ars_thread中的appid值,appid值在下载页面控制台可以看到。
- */
-
- public class OfflineAsrMain {
- //录音相关参数
- public static AudioFormat audioFormat;
- public static TargetDataLine targetDataLine;
- public static void main(String[] args) throws Exception {
- System.out.println("y开始体验离线命令词识别,n结束离线命令词识别");
- Scanner input = new Scanner(System.in);
- String inputContent = input.next();
- long startTime = System.currentTimeMillis();
- if(inputContent.equals("y")){
- audioFormat = Step3_audioFormat.getAudioFormat(audioFormat);//构造具有线性 PCM 编码和给定参数的 AudioFormat。
- DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
- targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
- Step2_asr_thread myThread=new Step2_asr_thread();
- myThread.start();
- Scanner input_2 = new Scanner(System.in);
- String inputContent_2 = input_2.next();
- if(inputContent_2.equals("n")){
- targetDataLine.stop();
- targetDataLine.close();
- }
- System.out.println("离线命令词识别操作持续:"+(System.currentTimeMillis()-startTime)/1000+"秒!");
- System.exit(0);
- }
- }
- }

2、根据MSC文档用JAVA重写方法
- package com.iflytek.service;
- import com.iflytek.util.Step1_grammar_callback;
- import com.iflytek.util.Step1_lexicon_callback;
- import com.sun.jna.Library;
- import com.sun.jna.Native;
- import com.sun.jna.ptr.IntByReference;
-
- public interface Step1_asr_dll extends Library {
- /**
- * 重点:
- * 1.char * 对应 String
- * 2.int * 对应 IntByReference
- * 3.void * 对应 byte[],回调函数里此类型也可以用String来对应。
- * 4.int 对应 int
- * 5.无参 对应 void
- * 6.回调函数 对应 根据文档自定义回调函数,实现接口Callback
- */
- //加载dll动态库并实例化,从而使用其内部的方法
- Step1_asr_dll INSTANCE = (Step1_asr_dll) Native.loadLibrary
- ("res/msc_x64.dll", Step1_asr_dll.class);
-
- //定义登录方法
- public int MSPLogin(String usr, String pwd, String params);
-
- //开始一次语音识别。
- public String QISRSessionBegin(String grammarList,String params,IntByReference errorCode);
-
- //写入本次识别的音频
- public int QISRAudioWrite(String sessionID, byte[] byteArrayAudioData,int waveLen,int audioStatus, IntByReference epStatus,IntByReference recogStatus);
-
- //获取识别结果。
- public String QISRGetResult(String sessionID,IntByReference rsltStatus,int waitTime, IntByReference errorCode);
-
- //结束本次语音识别。
- public int QISRSessionEnd(String sessionID,String hints);
-
- //获取当次语音识别信息,如上行流量、下行流量等
- public int QISRGetParam(String sessionID,String paramName,String paramValue, IntByReference valueLen);
-
- //构建语法,生成语法ID。有回调
- public int QISRBuildGrammar(String grammarType, String grammarContent, int grammarLength, String params, Step1_grammar_callback grammarCallBack, byte[] userData);
-
- //更新本地语法词典。有回调
- public int QISRUpdateLexicon(String lexiconName, String lexiconContent, int lexiconLength, String params, Step1_lexicon_callback lexiconCallback, byte[] userData);
-
- //定义退出方法
- public int MSPLogout();
- }

3、 构建语法回调函数
- package com.iflytek.util;
- import com.sun.jna.Callback;
-
- public class Step1_grammar_callback implements Callback {
- //根据文档写回调方法
- public int build_grm_cb(int errorCode,String info, String userData) {
- System.out.println("构建语法返回的ID信息...:"+info+"错误码"+errorCode+"\n");
- return 0;
- }
- }
4、更新词典回调函数
- package com.iflytek.util;
- import com.sun.jna.Callback;
-
- public class Step1_lexicon_callback implements Callback {
- //根据文档写回调方法
- public int LexiconCallBack(int errorCode, String info, String userData) {
- System.out.println("更新词典返回的信息...:"+info+"错误码:"+errorCode+"\n");
- return 0;
- }
- }
5、把调用步骤依次写进线程类
- package com.iflytek.util;
- import com.iflytek.OfflineAsrMain;
- import com.iflytek.service.Step1_asr_dll;
- import com.sun.jna.ptr.IntByReference;
- import javax.sound.sampled.AudioInputStream;
- import java.io.BufferedReader;
- import java.io.FileInputStream;
- import java.io.InputStreamReader;
-
- public class Step2_asr_thread extends Thread{
- public void run() {
- while (true) {
- //登录参数
- String login_config = "appid = 替换你的appid, work_dir = ./res";
- //第一个参数为用户名,第二个参数为密码,传null即可
- int ret = Step1_asr_dll.INSTANCE.MSPLogin(null, null, login_config);
- if (ret != 0) {//登录成功标志ret为0
- System.out.println("登录失败...请检查"+ret);
- System.exit(1);
- } else {
- //System.out.println("请注意,离线命令词call.bnf可以根据语法自定义...");
- }
-
- //读取call.bnf的内容
- FileInputStream fileInputStream = null;
- String grammarContent = "";
- try {
- fileInputStream = new FileInputStream("./res/call.bnf");
- InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
- BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
- String temp = "";
- while ((temp = bufferedReader.readLine()) != null) {
- grammarContent = grammarContent + temp + "\n";
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- //System.out.println("语法内容:\n" + grammarContent);
-
- //构建语法
- Step1_grammar_callback step2_grammar_callback = new Step1_grammar_callback();
- String params = "engine_type = local,asr_res_path = fo|res/asr/common.jet,sample_rate = 16000,grm_build_path = res/asr/GrmBuilld_x64";
- ret = Step1_asr_dll.INSTANCE.QISRBuildGrammar("bnf", grammarContent, grammarContent.getBytes().length, params, step2_grammar_callback, null);
- if (ret == 0) {
- //System.out.println("构建语法成功...");
- } else {
- System.out.println("构建语法失败:" + ret);
- }
-
- //更新本地语法词典
- /*String lexiconName = "enter";
- String lex_content = "登录软件";
- String lexParams = "engine_type=local,asr_res_path = fo|res/asr/common.jet, sample_rate = 16000,grm_build_path =res/asr/GrmBuilld_x64, grammar_list =call";
- Step3_lexicon_callback step3_lexicon_callback = new Step3_lexicon_callback();
- ret = Step1_asr_dll.INSTANCE.QISRUpdateLexicon(lexiconName, lex_content, lex_content.getBytes().length, lexParams, step3_lexicon_callback, null);
- if (ret == 0) {
- //System.out.println("更新本地语法词典成功...");
- } else {
- System.out.println("更新本地语法词典失败:" + ret);
- }*/
-
- //开始一次语音识别
- IntByReference errorCode = new IntByReference(-100);
- params = "vad_bos =4000 ,vad_eos = 10000,engine_type = local,asr_res_path = fo|res/asr/common.jet, sample_rate = 16000,grm_build_path = res/asr/GrmBuilld_x64, local_grammar = call,result_type = json, result_encoding = UTF8";
- String session_id = Step1_asr_dll.INSTANCE.QISRSessionBegin(null, params, errorCode);
- if (errorCode.getValue() == 0) {//只有返回0为函数调用成功
- System.out.println("本次会话开启成功...,会话id为:" + session_id);
- } else {
- System.out.println("本次会话开启失败:" + errorCode.getValue());
- }
-
- //写入识别的音频
- try {
- //给构建语法、更新本地语法词典点时间
- Thread.sleep(100);
- System.err.println("\033[43;34;4m" + "请开始说出命令..." + "\033[0m");
- //间隔400ms给用户反映时间
- Thread.sleep(500);
- } catch (Exception e) {
- e.printStackTrace();
- }
- IntByReference epStatus = new IntByReference(-100);
- IntByReference recogStatus = new IntByReference(-100);
- //16k采样率的16位音频,一帧的大小为640Byte(来自Windows SDK的说明)
- int frameSize = 640;
- //用来告知MSC音频发送是否完成
- int audioStatus = 1;
- //反复调用QISRAudioWrite写音频方法,直到音频写完为止
- //long startTime=System.currentTimeMillis();
- try {
- final byte[] audioDataByteArray = new byte[frameSize];
- while (true) {
- OfflineAsrMain.targetDataLine.open(OfflineAsrMain.audioFormat);
- OfflineAsrMain.targetDataLine.start();
- int len = new AudioInputStream(OfflineAsrMain.targetDataLine).read(audioDataByteArray);
- //long endTime=System.currentTimeMillis();//||endTime-startTime>60000
- if (len == -1 || epStatus.getValue() == 3) {//调用麦克风时候,len == -1将不会被执行...
- //||(endTime-startTime>60*1000)
- audioStatus = 4;//最后帧
- ret = Step1_asr_dll.INSTANCE.QISRAudioWrite(session_id, audioDataByteArray, len, audioStatus, epStatus, recogStatus);
- if (ret == 0) {
- //System.out.println("最后一帧音频写入正常");
- } else {
- System.out.println("最后一帧音频写入异常:" + ret);
- }
- Thread.sleep(1500);
- break; //文件读完,跳出循环
- } else {
- //反复调用
- ret = Step1_asr_dll.INSTANCE.QISRAudioWrite(session_id, audioDataByteArray, len, audioStatus, epStatus, recogStatus);
- }
- audioStatus = 2;//中间帧
- if (ret == 0) {
- //System.out.println("音频写入正常");
- } else {
- System.out.println("音频写入异常:" + ret);
- }
- // 如果是实时采集音频,可以省略此操作。5KB 大小的16KPCM 持续的时间是160 毫秒
- //Thread.sleep(160);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- //获取识别结果
- IntByReference rsltStatus = new IntByReference(-100);
- String grammarResult = Step1_asr_dll.INSTANCE.QISRGetResult(session_id, rsltStatus, 0, errorCode);
- if(grammarResult!=null){
- System.out.println("命令词识别结果:" + grammarResult);
- }
-
- //终止会话
- ret = Step1_asr_dll.INSTANCE.QISRSessionEnd(session_id, "正常终止");
- if (ret == 0) {
- //System.out.println("本次会话正常终止...");
- } else {
- System.out.println("本次会话异常终止...");
- }
-
- //执行退出
- ret = Step1_asr_dll.INSTANCE.MSPLogout();
- if (ret == 0) {
- //System.out.println("正常退出...");
- } else {
- System.out.println("异常退出...");
- }
- }
- }
- }

6、录音生成16K、16BIT单声道的音频流
- package com.iflytek.util;
- import javax.sound.sampled.AudioFormat;
-
- public class Step3_audioFormat {
- //构造线程参数
- //16k采样率的16bit音频,一帧的大小为640B, 时长20ms
- /**
- sampleRate - 每秒样品数
- sampleSizeInBits - 每个样本中的位数
- channels - 通道数(1为mono,2为立体声等)
- signed - 表示数据是签名还是无符号
- bigEndian - 指示单个样本的数据是否以大字节顺序存储( false表示小端)
- */
- public static AudioFormat getAudioFormat(AudioFormat audioFormat) {
- audioFormat=new AudioFormat(16000F, 16,
- 1,true,false);
- // true,false 指示是以 big-endian 顺序还是以 little-endian 顺序存储音频数据。
- return audioFormat;//构造具有线性 PCM 编码和给定参数的 AudioFormat。
- }
- }
-

7、放置讯飞开放平台下载Linux/Windows中所带的资源
8、Linux代码基本类似,注意加载SO库就行和放置资源
- package com.iflytek.service;
- import com.iflytek.OfflineAsrMain;
- import com.iflytek.util.Step1_grammar_callback;
- import com.iflytek.util.Step1_lexicon_callback;
- import com.sun.jna.Library;
- import com.sun.jna.Native;
- import com.sun.jna.ptr.IntByReference;
-
- public interface Step1_asr_so extends Library {
- /**
- * 重点:
- * 1.char * 对应 String
- * 2.int * 对应 IntByReference
- * 3.void * 对应 byte[],回调函数里此类型需用String来对应。
- * 4.int 对应 int
- * 5.无参 对应 void
- * 6.回调函数 对应 根据文档自定义回调函数,实现接口Callback
- */
- //加载so动态库并实例化,从而使用其内部的方法
- Step1_asr_so INSTANCE = (Step1_asr_so) Native.loadLibrary
- (OfflineAsrMain.userPath+"res/libmsc.so", Step1_asr_so.class);
-
- //定义登录方法
- public int MSPLogin(String usr, String pwd, String params);
-
- //开始一次语音识别。
- public String QISRSessionBegin(String grammarList,String params,IntByReference errorCode);
-
- //写入本次识别的音频
- public int QISRAudioWrite(String sessionID, byte[] byteArrayAudioData,int waveLen,int audioStatus, IntByReference epStatus,IntByReference recogStatus);
-
- //获取识别结果。
- public String QISRGetResult(String sessionID,IntByReference rsltStatus,int waitTime, IntByReference errorCode);
-
- //结束本次语音识别。
- public int QISRSessionEnd(String sessionID,String hints);
-
- //获取当次语音识别信息,如上行流量、下行流量等
- public int QISRGetParam(String sessionID,String paramName,String paramValue, IntByReference valueLen);
-
- //构建语法,生成语法ID。有回调
- public int QISRBuildGrammar(String grammarType, String grammarContent, int grammarLength, String params, Step1_grammar_callback grammarCallBack, byte[] userData);
-
- //更新本地语法词典。有回调
- public int QISRUpdateLexicon(String lexiconName, String lexiconContent, int lexiconLength, String params, Step1_lexicon_callback lexiconCallback, byte[] userData);
-
- //定义退出方法
- public int MSPLogout();
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。