說明:
1,百度語音極速版,需要事先保存聲音文件,然後調用百度接口。
2,關於文件的上傳,可以用JSON格式,上傳文件的base64編碼,也可以用row格式直接上傳文件。下面的代碼是JSON格式。
3,使用接口前需要向百度AI開放平臺註冊APPID,得到祕鑰,然後用得到的APPID和祕鑰來獲得TOKEN。調用百度語音接口時需要TOKEN。
4,百度提供了一個工具,可以從拼音角度判斷相似度,score越小說明拼音越相似,挺好用,非常適合需要匹配的場景。
5,相關Maven庫:
<dependency>
<groupId>com.github.stuxuhai</groupId>
<artifactId>jpinyin</artifactId>
<version>1.1.8</version>
</dependency>
上代碼:
package test;
import com.alibaba.fastjson.JSONObject;
import sun.misc.BASE64Encoder;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
/**
* 百度語音識別相關工具
*/
public class VopUtil {
public final static String URL = "https://vop.baidu.com/pro_api";
public final static String TOKEN = ""; //需要事先註冊
public final static String CUID = "zheshiyigeceshi"; //用戶唯一標識,用來區分用戶,計算UV值。建議填寫能區分用戶的機器 MAC 地址或 IMEI 碼,長度爲60字符以內。
public static void main(String[] args){
String filePath="D:\\語音test\\我要買美汁源果粒橙.wav"; //語音文件路徑,這個文件是我自己用手機的錄音機錄的一段語音,內容就是文件名
String base64=getBaset64(filePath); //文件轉爲base64格式
long fileLength=getFileLength(filePath); //獲得文件長度,單位字節
JSONObject vopResult = getVopStr(base64, fileLength); //調用百度語音識別接口
System.out.println("語音識別接口返回值:"+vopResult.toJSONString());
String errMsg = vopResult.get("err_msg").toString();
if (!"success.".equals(errMsg)) {
System.out.println("識別失敗");
}
String resultStr = vopResult.get("result").toString();
resultStr = resultStr.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "");
System.out.println("語音識別的結果:"+resultStr);
String[] nameArr={"可樂","雪碧","美年達","美汁源","紅牛","尖叫","牛奶","酸奶","百事"}; //備選名字列表,用於匹配拼音相似度
String targetName = getSimilarWord(resultStr, nameArr);
System.out.println("拼音最相似:"+targetName);
}
/**
* 請求百度語音識別接口
* @param file 文件的base64編碼
* @param len 文件長度,字節數
* @return
*/
public static JSONObject getVopStr(String file,long len) {
JSONObject params = new JSONObject(true);
params.put("format", "wav");
params.put("rate", 16000);
params.put("channel", 1);
params.put("cuid", CUID);
params.put("token", TOKEN);
params.put("dev_pid", 80001);
params.put("len", len);
params.put("speech", file);
String result = "";
BufferedReader reader = null;
BufferedReader in = null;
try {
URL url = new URL(URL);// 創建連接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod("POST"); // 設置請求方式
connection.setRequestProperty("Accept", "application/json"); // 設置接收數據的格式
connection.setRequestProperty("Content-Type", "application/json"); // 設置發送數據的格式
connection.connect();
if (params != null) {
// 設置文件長度
// connection.setRequestProperty("Content-Length", String.valueOf(writebytes.length));
OutputStream outwritestream = connection.getOutputStream();
outwritestream.write(params.toJSONString().getBytes());
outwritestream.flush();
outwritestream.close();
}
int responseCode = connection.getResponseCode();
InputStream inputStream = null;
if (responseCode == 200) {
inputStream = new BufferedInputStream(connection.getInputStream());
} else {
inputStream = new BufferedInputStream(connection.getErrorStream());
}
in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return JSONObject.parseObject(result);
}
/**
* 從目標字符串列表中查詢拼音最相似的字符串
* @param input 待查詢的字符串
* @param arr 備選詞語庫
* @return
*/
public static String getSimilarWord(String input,String[] arr){
try {
Search d = new Search(arr);
List<Search.Score> list=d.search(input,10);
System.out.println("拼音相似度列表:"+list);
if(list!=null&&list.size()>0){
Search.Score score=list.get(0);
return score.word.toString();
}
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 文件轉base64
* @param filePath 文件路徑
* @return
*/
private static String getBaset64(String filePath){
String base64="";
try {
File file = new File(filePath);
FileInputStream inputFile = new FileInputStream(file);
byte[] buffer = new byte[(int)file.length()];
inputFile.read(buffer);
inputFile.close();
base64= new BASE64Encoder().encode(buffer);
if(base64.contains("\n")){
base64=base64.replaceAll("\n","");
}
if(base64.contains("\r")){
base64=base64.replaceAll("\r","");
}
}catch (Exception e){
e.printStackTrace();
}
return base64;
}
/**
* 得到文件大小,單位:字節
* @param filePath 文件路徑
* @return
*/
private static long getFileLength(String filePath){
File file = new File(filePath);
long fileLength=file.length();
return fileLength;
}
}
下面是Search類,這個類是百度提供的:
package test;
import com.github.stuxuhai.jpinyin.PinyinException;
import com.github.stuxuhai.jpinyin.PinyinFormat;
import com.github.stuxuhai.jpinyin.PinyinHelper;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 本文件用來演示如何通過文本相似度進行糾錯
* <p>
* <pre>
* String[] list = new String[]{"張三", "張衫", "張丹", "張成", "李四", "李奎"};
* Search d = new Search(list);
* System.out.println(d.search("張三", 10));
* System.out.println(d.search("李四", 10));
*
* 輸出:
* [{word=張三, score=0}, {word=張衫, score=1}, {word=張丹, score=1}, {word=張成, score=5}, {word=李四, score=9}, {word=李奎, score=10}]
* [{word=李四, score=0}, {word=李奎, score=3}, {word=張三, score=9}, {word=張衫, score=10}, {word=張丹, score=10}, {word=張成, score=12}]
* </pre>
*/
public class Search {
final List<Word> targets = new ArrayList<Word>();
public Search(String[] list) throws PinyinException {
for (String s : list) {
Word w = new Word(s);
targets.add(w);
}
}
public List<Score> search(String input, int limit) throws PinyinException {
Word w = new Word(input);
return targets.stream().map(x -> {
Score s = new Score();
s.word = x;
s.score = x.compareTo(w);
return s;
}).sorted().limit(limit).collect(Collectors.toList());
}
public static int getEditDistance(String s, String t) {
int d[][]; // matrix
int n; // length of s
int m; // length of t
int i; // iterates through s
int j; // iterates through t
char s_i; // ith character of s
char t_j; // jth character of t
int cost; // cost
// Step 1
n = s.length();
m = t.length();
if (n == 0) {
return m;
}
if (m == 0) {
return n;
}
d = new int[n + 1][m + 1];
// Step 2
for (i = 0; i <= n; i++) {
d[i][0] = i;
}
for (j = 0; j <= m; j++) {
d[0][j] = j;
}
// Step 3
for (i = 1; i <= n; i++) {
s_i = s.charAt(i - 1);
// Step 4
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
// Step 5
cost = (s_i == t_j) ? 0 : 1;
// Step 6
d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1,
d[i - 1][j - 1] + cost);
}
}
// Step 7
return d[n][m];
}
private static int Minimum(int a, int b, int c) {
int im = a < b ? a : b;
return im < c ? im : c;
}
class Word implements Comparable {
final String word;
final String pinyin1;
final String pinyin2;
Word(String word) throws PinyinException {
this.word = word;
this.pinyin1 = PinyinHelper.convertToPinyinString(word, ",", PinyinFormat.WITH_TONE_NUMBER);
this.pinyin2 = PinyinHelper.convertToPinyinString(word, ",", PinyinFormat.WITHOUT_TONE);
}
@Override
public String toString() {
return word;
}
@Override
public int compareTo(Object o) {
if (o instanceof Word) {
Word o1 = (Word) o;
int score1 = getEditDistance(this.pinyin1, o1.pinyin1);
int score2 = getEditDistance(this.pinyin2, o1.pinyin2);
return score1 + score2;
}
return 0;
}
}
class Score implements Comparable {
Word word;
int score;
@Override
public int compareTo(Object o) {
if (o instanceof Score) {
return score - ((Score) o).score;
}
return 0;
}
@Override
public String toString() {
return "{" +
"word=" + word +
", score=" + score +
'}';
}
}
}
本地執行main方法後的輸出結果:
語音識別接口返回值:{"result":["我要買美汁源果粒橙。"],"err_msg":"success.","sn":"275665891801562141461","corpus_no":"6709346487565939628","err_no":0}
語音識別的結果:我要買美汁源果粒橙。
拼音相似度列表:[{word=美汁源, score=58}, {word=美年達, score=66}, {word=百事, score=73}, {word=紅牛, score=74}, {word=尖叫, score=74}, {word=酸奶, score=75}, {word=可樂, score=76}, {word=牛奶, score=76}, {word=雪碧, score=77}]
拼音最相似:美汁源