参考:官方文档,http://blog.youkuaiyun.com/lw_power/article/details/51771267
1、注册成为百度开发者,创建应用,得到 API Key 和 Secret Key。
略。
2、开通语音识别服务。
略
3、获取 Access Token,语音解析关键代码:
package com.robin;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.DatatypeConverter;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
public class VoiceDemo {
/**
* 请求语音识别的时候使用
*/
private static final String speech_recognition_url = "http://vop.baidu.com/server_api";
/**
* getLocalMac <获取本地mac>
* <这里描述这个方法适用条件>
* @param ia
* @throws SocketException
* void
* @exception
* @since [产品/模块版本]
*/
private static String getLocalMac(InetAddress ia) throws SocketException {
// TODO Auto-generated method stub
//获取网卡,获取地址
byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
//System.out.println("mac数组长度:"+mac.length);
StringBuffer sb = new StringBuffer("");
for(int i=0; i<mac.length; i++) {
if(i!=0) {
sb.append("-");
}
//字节转换为整数
int temp = mac[i]&0xff;
String str = Integer.toHexString(temp);
//System.out.println("每8位:"+str);
if(str.length()==1) {
sb.append("0"+str);
}else {
sb.append(str);
}
}
//System.out.println("本机MAC地址:"+sb.toString().toUpperCase());
return sb.toString().toUpperCase();
}
/**
*
* getToken <获取token> <这里描述这个方法适用条件>
*
* @return Map<String,Object> 返回MAP对象
* @exception @since
* [产品/模块版本]
*/
@SuppressWarnings("unchecked")
public static Map<String, Object> getToken() {
Map<String, Object> map = new HashMap<String, Object>();
String apiKey = "申请的apiKey";
String secretKey = "申请的secretKey";
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost("https://openapi.baidu.com/oauth/2.0/token");
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("grant_type", "client_credentials"));
nvps.add(new BasicNameValuePair("client_id", apiKey));
nvps.add(new BasicNameValuePair("client_secret", secretKey));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
int status = response.getStatusLine().getStatusCode();
if (status >= 200 && status < 300) {
HttpEntity entity = response.getEntity();
try {
return entity != null ? EntityUtils.toString(entity) : null;
} catch (ParseException ex) {
throw new ClientProtocolException(ex);
}
} else {
throw new ClientProtocolException("Unexpected response status: " + status);
}
}
};
String responseBody = httpClient.execute(httpPost, responseHandler);
//System.out.println(responseBody);
map = (Map<String, Object>) JSON.parse(responseBody);
/*Set<String> setKey = map.keySet();
Iterator<String> it = setKey.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str + "=" + map.get(str));
}*/
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
/**
*
* recognize <语音识别> <这里描述这个方法适用条件>
*
* @param wavName
* 文件路径
* @param language
* 语言
* @throws Exception
* void
* @exception @since
* [产品/模块版本]
*/
private static void recognize(String audioName, String language) throws Exception {
File audioFile = new File(audioName);
HttpPost httpPost = null;
//CloseableHttpResponse response = null;
CloseableHttpClient httpClient = HttpClients.createDefault();
httpPost = new HttpPost(speech_recognition_url);
SpeechRecognitionRequestEntity requestEntity = new SpeechRecognitionRequestEntity();
// 语音压缩的格式:请按照官网文档填写 pcm(不压缩)、wav、opus、speex、amr、x-flac 之一,不区分大小写
requestEntity.setFormat("pcm");
// 声道数,仅支持单声道,请填写 1
requestEntity.setChannel("1");
// 采样率,支持 8000 或者 16000 (这个类型是 int ,不能设置为 String 类型,关于采样率如何转换,请见下文)
requestEntity.setRate(16000);
// todo 这里应判断 AccessToken 是否过期,处理异常,如果过期了,应该重新获取 accessToken
requestEntity.setToken(getToken().get("access_token").toString());
// Cuid 推荐使用设备 mac 地址 手机 IMEI 等设备唯一性参数
InetAddress ia = InetAddress.getLocalHost();
requestEntity.setCuid(getLocalMac(ia));
requestEntity.setLen(audioFile.length());
// 官网说: speech 要传递真实的语音数据,需要进行 base64 编码
// 重点关注:请见后面封装的方法,就是把一个文件转换成为指定格式的字节数组
requestEntity.setSpeech(DatatypeConverter.printBase64Binary(handlerAudioFile(audioFile)));
// 语种选择,中文=zh、粤语=ct、英文=en,不区分大小写,默认中文
requestEntity.setLan(language);
// 关键点 1 :将请求参数转换为 json 格式
String requestEntityJson = JSON.toJSONString(requestEntity);
// 关键点 2 :封装 StringEntity ,为解决中文乱码问题,应该设置编码
StringEntity entity = new StringEntity(requestEntityJson.toString(), "UTF-8");
entity.setContentEncoding("UTF-8");
// 关键点 3 :设置 StringEntity 的 ContentType
entity.setContentType("application/json");
httpPost.setEntity(entity);
ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
@Override
public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
String resData = null;
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode >= 200 && statusCode < 300) {
HttpEntity httpEntity = response.getEntity();
resData = EntityUtils.toString(httpEntity, "utf-8");
EntityUtils.consume(httpEntity);
}
return resData;
}
};
try {
String responseStr = httpClient.execute(httpPost, responseHandler);
System.out.println(responseStr);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* handlerAudioFile <语音转码>
* <这里描述这个方法适用条件>
* @param file
* @return
* @throws Exception
* byte[]
* @exception
* @since [产品/模块版本]
*/
public static byte[] handlerAudioFile(File file) throws Exception {
InputStream is = new FileInputStream(file);
long length = file.length();
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
is.close();
throw new IOException("Could not completely read file " + file.getName());
}
is.close();
return bytes;
}
public static void main(String[] args) throws Exception {
recognize("C:\\Users\\bbjiang\\Downloads\\16k.pcm", "zh");
}
}
4、用到的实体类:
package com.robin;
public class SpeechRecognitionRequestEntity {
// 语音压缩的格式
private String format;
/**
* 注意,采样率的数据类型一定是 int,不能是 String
*/
// 采样率,支持 8000 或者 16000,在我们的项目中,写 16000
private int rate;
// 声道数,仅支持单声道,请填写 1
private String channel;
// 开发者身份验证密钥
private String token;
// 用户 ID,推荐使用设备 mac 地址 手机 IMEI 等设备唯一性参数
// todo 貌似可以随意填写,唯一即可
private String cuid;
/**
* 注意:这里填写的是原始语音的长度,不是使用 base64 编码的语音长度
*/
// 原始语音长度,单位字节
private long len;
// 真实的语音数据,需要进行 base64 编码
private String speech;
// 语种选择,中文=zh、粤语=ct、英文=en,不区分大小写,默认中文
private String lan;
public String getFormat() {
return format;
}
public void setFormat(String format) {
this.format = format;
}
public int getRate() {
return rate;
}
public void setRate(int rate) {
this.rate = rate;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getCuid() {
return cuid;
}
public void setCuid(String cuid) {
this.cuid = cuid;
}
public long getLen() {
return len;
}
public void setLen(long len) {
this.len = len;
}
public String getSpeech() {
return speech;
}
public void setSpeech(String speech) {
this.speech = speech;
}
public String getLan() {
return lan;
}
public void setLan(String lan) {
this.lan = lan;
}
}
5、用到的JAR包:
6、用到的示例文件: