jacob和百度語音合成 播報的實現形式
阿新 • • 發佈:2019-02-06
有個語音播報的需求,這些日子查了一些資料,在這裡總結一下,一些工具類和檔案我已經放到了下載路徑上,下面提供
1,jacob
引入maven
<!-- https://mvnrepository.com/artifact/net.sf.jacob-project/jacob --> <dependency> <groupId>net.sf.jacob-project</groupId> <artifactId>jacob</artifactId> <version>1.14.3</version> </dependency>
將jacob-1.14.3-x64放在jdk的bin中,和C:\WINDOWS\System32中,注意放入的jacob和maven下載版本要一致
實現程式碼如下
public static void stratVoice(String content, int type) { ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice"); Dispatch sapo = sap.getObject(); if (type == 0) { try { // 音量 0-100 sap.setProperty("Volume", new Variant(100)); // 語音朗讀速度 -10 到 +10 sap.setProperty("Rate", new Variant(0)); Variant defalutVoice = sap.getProperty("Voice"); Dispatch dispdefaultVoice = defalutVoice.toDispatch(); Variant allVoices = Dispatch.call(sapo, "GetVoices"); Dispatch dispVoices = allVoices.toDispatch(); Dispatch setvoice = Dispatch.call(dispVoices, "Item", new Variant(1)).toDispatch(); ActiveXComponent voiceActivex = new ActiveXComponent( dispdefaultVoice); ActiveXComponent setvoiceActivex = new ActiveXComponent( setvoice); Variant item = Dispatch.call(setvoiceActivex, "GetDescription"); // 執行朗讀 Dispatch.call(sapo, "Speak", new Variant(content)); } catch (Exception e) { log.info("錯誤:", e); e.printStackTrace(); } finally { sapo.safeRelease(); sap.safeRelease(); } } else { // 停止 try { Dispatch.call(sapo, "Speak", new Variant(content), new Variant( 2)); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } }
引用
public static void main(String[] args) {
VoiceUtil.stratVoice("桃之夭夭,灼灼其華。之子于歸,宜其室家。\n" +
"桃之夭夭,有蕡其實。之子于歸,宜其家室。\n" +
"桃之夭夭,其葉蓁蓁。之子于歸,宜其家人", 0);
}
可以自己玩一下引數
2,百度語音合成(服務端播報)
可以先看下文件瞭解下,下面先引maven
<!-- https://mvnrepository.com/artifact/com.baidu.aip/java-sdk --> <dependency> <groupId>com.baidu.aip</groupId> <artifactId>java-sdk</artifactId> <version>4.3.2</version> </dependency>
這是主要程式碼,具體去連結下載即可
public String voiceRun(HttpServletRequest request){
try {
TokenHolder holder = new TokenHolder(appKey, secretKey, TokenHolder.ASR_SCOPE);
holder.refresh();
String token = holder.getToken();
// 此處2次urlencode, 確保特殊字元被正確編碼
String params = "tex=" + ConnUtil.urlEncode(ConnUtil.urlEncode(text));
params += "&per=" + per;
params += "&spd=" + spd;
params += "&pit=" + pit;
params += "&vol=" + vol;
params += "&cuid=" + cuid;
params += "&tok=" + token;
params += "&aue=" + aue;
params += "&lan=zh&ctp=1";
log.info("反饋請帶上此url,瀏覽器上可以測試:{}", url + "?" + params); // 反饋請帶上此url,瀏覽器上可以測試
HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
PrintWriter printWriter = new PrintWriter(conn.getOutputStream());
printWriter.write(params);
printWriter.close();
String contentType = conn.getContentType();
if (contentType.contains("audio/")) {
byte[] bytes = ConnUtil.getResponseBytes(conn);
String format = getFormat(aue);
// 第二種:獲取專案路徑
File directory = new File("");// 引數為空
String path = request.getSession().getServletContext().getRealPath("/");
System.out.println(path);
File file = new File(path + "result." + format); // 開啟mp3檔案即可播放
FileOutputStream os = new FileOutputStream(file);
os.write(bytes);
os.close();
log.info("儲存路徑:{}", file.getAbsolutePath());
// boolean ret = voiceStart(format);
// log.info("播放結果:{}", ret);
return "success";
} else {
System.err.println("ERROR: content-type= " + contentType);
String res = ConnUtil.getResponseString(conn);
System.err.println(res);
return null;
}
}catch (Exception e){
return null;
}
}
request.getSession().getServletContext().getRealPath("/");這個獲取的是專案根目錄,是wav檔案的存放路徑,等會播報會用到
播放wav
public static boolean voiceStart(String format) {
try {
log.info("播放開始,{}", System.getProperty("user.dir"));
// 1.wav 檔案放在java project 下面 即可播放
FileInputStream fileau = new FileInputStream(
System.getProperty("user.dir") + "\\result." + format);
AudioStream as = null;
as = new AudioStream(fileau);
AudioPlayer.player.start(as);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
這裡面播報用到的路徑我沒改,不應該用System.getProperty("user.dir")這個獲取,我當時就沒獲取到這個路徑,也應該用剛才存路徑的那個request.getSession().getServletContext().getRealPath("/"),如果你本地main測試可以先寫死
wav檔案保留30天,30天后失效,所以播報可以放在外面,30天內都可以直接呼叫播報即可,不用重複生成,還要想辦法如何在30天內最低會呼叫一次voiceRun合成語音介面,使wav檔案不至於失效播報不出來,這個就自己想辦法吧
因為是伺服器端播報,如果想聽到聲音要遠端連線,如果關閉了連線就聽不到了,這個如果有大神知道如何解決這個問題請留言告知
3,百度語音合成:客戶端播報
客戶端可以先用上面已用voiceRun生成wav檔案,然後定義一個div
<div id="emb"></div>
用js實現業務呼叫
function myrefresh() {
$.ajax({
type: "GET",
url: "/server/status",
dataType: "json",
data: "",
success: function (data) {
var res = data.res;
if (res != 0) {
//根據業務
var data = "<embed id=\"wavFileId\"\n" +
" src=\"/YQStore/result.wav\"\n" +
" width=\"0\"\n" +
" height=\"0\"\n" +
" loop=\"false\"\n" +
" autostart=\"false\">\n" +
"</embed>";
$('#emb').html(data);
console.log("語音提醒")
try {
var node = document.getElementById('wavFileId');
if(node!=null){
node.Play();
}
} catch (err) {
console.log("err->" + err)
}
}
setTimeout('myrefresh()', 5000); //指定5秒重新整理一次
},
error: function () {
setTimeout('myrefresh()', 5000); //指定5秒重新整理一次
}
});
}
setTimeout('myrefresh()', 5000);
5s鍾重新整理一次根據業務進行播報,src就是wav後端存的路徑
這樣就可以實現在本地可以聽到語音播報了,但是有個缺點就是如果不在當前頁面就會聽不到聲音,不過可以將頁面單獨拉出來放在後面,再操作自己的網頁就不影響播報了,如果有大神有更好的辦法望告知,謝謝