【JAVA】使用百度语音识别 Rest API,遇到识别结果显示乱码的问题和解决
文章目录遇到乱码问题百度语音识别 Rest APIRest API 的使用乱码现象和解决过程1. 乱码现象2. 解决过程遇到乱码问题在使用百度语音识别 JAVA Rest API 的时候,把应用部署到外部Tomcat,发现返回的语音识别结果是乱码,而在IDEA上测试API,返回的结果正常。百度语音识别 Rest API短语音识别 简介GitHub地址处理、上传文件,获取识别结果。过程:com/ba
遇到乱码问题
在使用百度语音识别 JAVA Rest API 的时候,把应用部署到外部Tomcat,
发现返回的语音识别结果是乱码,而在IDEA上测试API,返回的结果正常。
百度语音识别 Rest API
处理、上传文件,获取识别结果。过程:
com/baidu/speech/restapi/asrdemo/ AsrMain.java
public static void main(String[] args) throws IOException, DemoException {
AsrMain demo = new AsrMain();
String result = demo.run();
// 打印识别结果result
log.info("识别结束:结果是:");
log.info(result);
}
public String run() throws IOException, DemoException {
...
// 以Json方式上传文件,获取返回的字符串
result = runJsonPostMethod(token);
...
return result;
}
// 默认以Json方式上传文件
// 注:本文作者添加:传入了参数 WAV文件路径+文件名
private String runJsonPostMethod(String token, String fileName) throws IOException, DemoException {
...
byte[] content = getFileContent(fileName);
String speech = base64Encode(content);
...
// 从HttpURLConnection 获取返回的字符串
String result = ConnUtil.getResponseString(conn);
...
return result;
}
// 将文件读取到FileInputStream,作为bytes返回
private byte[] getFileContent(String fileName) throws IOException{
File file = new File(fileName);
if (!file.canRead()) {
log.error("文件不存在或者不可读: " + file.getAbsolutePath());
}
try(FileInputStream fileInputStream = new FileInputStream(file)) {
// 将InputStream内的内容全部读取,作为bytes返回
return ConnUtil.getInputStreamContent(fileInputStream);
} catch (Exception e) {
log.error("读取文件到输入流过程错误:" + e.getMessage(), e);
return null;
}
}
com/baidu/speech/restapi/common/ ConnUtil.java:
// 从HttpURLConnection 获取返回的字符串
public static String getResponseString(HttpURLConnection conn) throws IOException {
// 从连接信息返回的内容
return new String(getResponseBytes(conn));
}
// 从HttpURLConnection 获取返回的 bytes
public static byte[] getResponseBytes(HttpURLConnection conn) throws IOException, DemoException {
int responseCode = conn.getResponseCode();
InputStream inputStream = conn.getInputStream();
...
byte[] result = getInputStreamContent(inputStream);
return result;
}
// 将InputStream内的内容全部读取,作为bytes返回
public static byte[] getInputStreamContent(InputStream is) throws IOException {
byte[] b = new byte[1024];
// 定义一个输出流存储接收到的数据
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
// 开始接收数据
int len = 0;
while (true) {
len = is.read(b);
if (len == -1) {
// 数据读完
break;
}
byteArrayOutputStream.write(b, 0, len);
}
return byteArrayOutputStream.toByteArray();
}
Rest API 的使用
String myApiKey = "myApiKey";
String mySecretKey = "mySecretKey";
String fileName = "D:/test.wav";
// 获得token: TokenHolder为API的 common 包中的类
TokenHolder holder =
new TokenHolder(myApiKey, mySecretKey, "audio_voice_assistant_get");
holder.resfresh();
String token = holder.getToken();
// 默认以json方式上传音频文件
String result = runJsonPostMethod(token, fileName);
// 解析返回的json字符串
JsonParser jsonParser = new JsonParser();
// 将json字符串转化成json对象
JsonObject jsonObject = jsonParser.parse(result).getAsJsonObject();
// 返回结果中的错误码。若错误码为0,则识别成功。
String stringErrorNumber = jsonObject.get("err_no").getAsString();
// 返回结果中的语音识别文字段落
String stringErrorMessage = jsonObject.get("err_msg").getAsString();
int errorNumber;
if(stringErrorNumber != null) {
errorNumber = Integer.valueOf(stringErrorNumber);
} else {
errorNumber = 0;
}
// 根据错误码,进行简单分类
switch (errorNumber) {
case 0: // 识别成功
log.info("识别结束,结果是:" + jsonObject.get("result").getAsString());
break;
case 3307: // recognition error 识别出错,无法识别
// TO-DO
break;
case 3308: // speech too long 音频文件时长过
// TO-DO
break;
default: // 识别不成功
log.error("百度ASR结果错误:" + wavFullName
+ ",错误代码:" + errorNumber
+ ",错误信息:" + stringErrorMessage);
}
乱码现象和解决过程
1. 乱码现象
用1个时长不到60s的,符合百度短语音识别 REST API 格式的,WAV文件,用IDEA测试,结果:
可见,result 里边显示的是正常的中文识别结果。
打包应用,部署到外部Tomcat,运行测试,也识别成功,日志显示却是乱码:
2. 解决过程
尝试修改Tomcat编码,改 UTF-8,或者改GBK,都无效;
解决各种tomcat中文乱码问题
修复tomcat9.0中文乱码问题
tomcat配置及中文乱码问题的解决方案
在JAVA代码中,用 String(str.getBytes(“GBK”), “UTF-8”); 也无效:
知乎:java中GBK编码格式转成UTF8,用一段方法实现怎么做?
public static String recover(String str) throws Throwable {
return new String(str.getBytes("GBK"), "UTF-8");
}
使用后,依旧乱码:
String jsonBack = new String(jsonBack.getBytes("GBK"), StandardCharsets.UTF_8);
log.info("ASR结果: " + jsonBack);
然后,某天在网上看到这两个图:
搜了一下,发现相关文章:
[转载]字符乱码说明
看上去,本文遇上的是第一种情况:以GBK方式读取UTF-8编码的中文,百度API返回的结果就是UTF-8格式,这应该不用怀疑的,在IDEA内部Tomcat的UTF-8环境下测试都显示正常。但尝试过修改了外部Tomcat的编码,没用。干脆从JAVA代码切入,看看能不能修改一点代码就能解决。
在获取识别的返回结果中,寻找能够设置字符串String编码格式的地方。从最底层的
getResponseBytes(HttpURLConnection conn) 和 getInputStreamContent(InputStream is) 看起,两个函数中没发现字符串String。
继续往上,发现 getResponseString(HttpURLConnection conn) 里边有 new String:
// 从HttpURLConnection 获取返回的字符串
public static String getResponseString(HttpURLConnection conn) throws IOException {
// 从连接信息返回的内容
return new String(getResponseBytes(conn));
}
于是,直接尝试加入UTF-8编码格式:
public static String getResponseString(HttpURLConnection conn) throws IOException {
// 从连接信息返回的内容,先用UTF-8解码
return new String(getResponseBytes(conn), StandardCharsets.UTF_8);
}
部署到外部Tomcat测试,结果显示正常!!!
更多推荐
所有评论(0)