本文介紹如何使用阿里云智能語音服務提供的Java SDK,包括SDK的安裝方法及SDK代碼示例。
前提條件
在使用SDK之前,請先閱讀接口說明,詳情請參見接口說明。
下載安裝
從Maven服務器下載最新版本SDK。
<dependency> <groupId>com.alibaba.nls</groupId> <artifactId>nls-sdk-tts</artifactId> <version>2.2.14</version> </dependency> <dependency> <groupId>com.alibaba.nls</groupId> <artifactId>nls-sdk-common</artifactId> <version>2.2.14</version> </dependency>
重要Java SDK 從 2.1.7 版本開始(含2.1.7),waitForComplete 接口的超時時間單位從 秒 變更為 毫秒 。
解壓該ZIP文件。
在pom.xml文件所在的目錄運行
mvn package
,會在target目錄生成可執行JAR:nls-example-tts-2.0.0-jar-with-dependencies.jar。將JAR包拷貝到您應用所在的服務器,用于快速驗證及壓測服務。
服務驗證。
運行如下代碼,并按提示提供相應參數。運行后在命令執行目錄生成logs/nls.log。
java -cp nls-example-tts-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechSynthesizerDemo
服務壓測。
運行如下代碼,并按提示提供相應參數。其中阿里云服務URL參數為:
wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1
,并發數根據您的購買情況進行選擇。java -jar nls-example-tts-2.0.0-jar-with-dependencies.jar
重要自行壓測超過2路并發將產生費用。
關鍵接口
NlsClient:語音處理客戶端,利用該客戶端可以進行一句話識別、實時語音識別和語音合成的語音處理任務。該客戶端為線程安全,建議全局僅創建一個實例。
SpeechSynthesizer:語音合成處理類,通過該接口設置請求參數,發送請求。非線程安全。
SpeechSynthesizerListener:語音合成監聽類,監聽返回結果。非線程安全。需要實現如下兩個抽象方法:
/** * 接收語音合成二進制數據 */ abstract public void onMessage(ByteBuffer message); /** * 語音合成結束事件通知 * * @param response */ abstract public void onComplete(SpeechSynthesizerResponse response);
更多介紹,請參見Java API接口說明。
SDK調用注意事項:
NlsClient使用Netty框架,NlsClient對象的創建會消耗一定時間和資源,一經創建可以重復使用。建議調用程序將NlsClient的創建和關閉與程序本身的生命周期相結合。
SpeechSynthesizer對象不可重復使用,一個語音合成任務對應一個SpeechSynthesizer對象。例如,N個文本要進行N次語音合成任務,創建N個SpeechSynthesizer對象。
SpeechSynthesizerListener對象和SpeechSynthesizer對象是一一對應的,不能將一個SpeechSynthesizerListener對象設置到多個SpeechSynthesizer對象中,否則不能將各語音合成任務區分開。
Java SDK依賴Netty網絡庫,如果您的應用依賴Netty,其版本需更新至4.1.17.Final及以上。
代碼示例
示例中使用SDK內置的默認語音合成服務的外網訪問服務URL,如果您使用位于阿里云上海地域的ECS,且需要通過內網訪問服務URL,則在創建NlsClient對象時,設置內網訪問的URL:
client = new NlsClient("wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1", accessToken);
示例中將合成的音頻保存在文件中,如果您需要播放音頻且對實時性要求較高,建議使用流式播放,即邊接收語音數據邊播放,減少延時。
調用接口前,需配置環境變量,通過環境變量讀取訪問憑證。智能語音交互的AccessKey ID、AccessKey Secret和AppKey的環境變量名:ALIYUN_AK_ID、ALIYUN_AK_SECRET、NLS_APP_KEY。
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.OutputFormatEnum;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 此示例演示了:
* 語音合成API調用。
* 動態獲取token。獲取Token具體操作,請參見:http://bestwisewords.com/document_detail/450514.html
* 流式合成TTS。
* 首包延遲計算。
*/
public class SpeechSynthesizerDemo {
private static final Logger logger = LoggerFactory.getLogger(SpeechSynthesizerDemo.class);
private static long startTime;
private String appKey;
NlsClient client;
public SpeechSynthesizerDemo(String appKey, String accessKeyId, String accessKeySecret) {
this.appKey = appKey;
//應用全局創建一個NlsClient實例,默認服務地址為阿里云線上服務地址。
//獲取token,使用時注意在accessToken.getExpireTime()過期前再次獲取。
AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
try {
accessToken.apply();
System.out.println("get token: " + accessToken.getToken() + ", expire time: " + accessToken.getExpireTime());
client = new NlsClient(accessToken.getToken());
} catch (IOException e) {
e.printStackTrace();
}
}
public SpeechSynthesizerDemo(String appKey, String accessKeyId, String accessKeySecret, String url) {
this.appKey = appKey;
AccessToken accessToken = new AccessToken(accessKeyId, accessKeySecret);
try {
accessToken.apply();
System.out.println("get token: " + accessToken.getToken() + ", expire time: " + accessToken.getExpireTime());
if(url.isEmpty()) {
client = new NlsClient(accessToken.getToken());
}else {
client = new NlsClient(url, accessToken.getToken());
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static SpeechSynthesizerListener getSynthesizerListener() {
SpeechSynthesizerListener listener = null;
try {
listener = new SpeechSynthesizerListener() {
File f=new File("tts_test.wav");
FileOutputStream fout = new FileOutputStream(f);
private boolean firstRecvBinary = true;
//語音合成結束
@Override
public void onComplete(SpeechSynthesizerResponse response) {
//調用onComplete時表示所有TTS數據已接收完成,因此為整個合成數據的延遲。該延遲可能較大,不一定滿足實時場景。
System.out.println("name: " + response.getName() +
", status: " + response.getStatus()+
", output file :"+f.getAbsolutePath()
);
}
//語音合成的語音二進制數據
@Override
public void onMessage(ByteBuffer message) {
try {
if(firstRecvBinary) {
//計算首包語音流的延遲,收到第一包語音流時,即可以進行語音播放,以提升響應速度(特別是實時交互場景下)。
firstRecvBinary = false;
long now = System.currentTimeMillis();
logger.info("tts first latency : " + (now - SpeechSynthesizerDemo.startTime) + " ms");
}
byte[] bytesArray = new byte[message.remaining()];
message.get(bytesArray, 0, bytesArray.length);
fout.write(bytesArray);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFail(SpeechSynthesizerResponse response){
//task_id是調用方和服務端通信的唯一標識,當遇到問題時需要提供task_id以便排查。
System.out.println(
"task_id: " + response.getTaskId() +
//狀態碼 20000000 表示識別成功
", status: " + response.getStatus() +
//錯誤信息
", status_text: " + response.getStatusText());
}
};
} catch (Exception e) {
e.printStackTrace();
}
return listener;
}
public void process() {
SpeechSynthesizer synthesizer = null;
try {
//創建實例,建立連接。
synthesizer = new SpeechSynthesizer(client, getSynthesizerListener());
synthesizer.setAppKey(appKey);
//設置返回音頻的編碼格式
synthesizer.setFormat(OutputFormatEnum.WAV);
//設置返回音頻的采樣率
synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
//發音人
synthesizer.setVoice("siyue");
//語調,范圍是-500~500,可選,默認是0。
synthesizer.setPitchRate(100);
//語速,范圍是-500~500,默認是0。
synthesizer.setSpeechRate(100);
//設置用于語音合成的文本
synthesizer.setText("歡迎使用阿里巴巴智能語音合成服務,您可以說北京明天天氣怎么樣啊");
// 是否開啟字幕功能(返回相應文本的時間戳),默認不開啟,需要注意并非所有發音人都支持該參數。
synthesizer.addCustomedParam("enable_subtitle", false);
//此方法將以上參數設置序列化為JSON格式發送給服務端,并等待服務端確認。
long start = System.currentTimeMillis();
synthesizer.start();
logger.info("tts start latency " + (System.currentTimeMillis() - start) + " ms");
SpeechSynthesizerDemo.startTime = System.currentTimeMillis();
//等待語音合成結束
synthesizer.waitForComplete();
logger.info("tts stop latency " + (System.currentTimeMillis() - start) + " ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
//關閉連接
if (null != synthesizer) {
synthesizer.close();
}
}
}
public void shutdown() {
client.shutdown();
}
public static void main(String[] args) throws Exception {
String appKey = System.getenv().get("NLS_APP_KEY");
String id = System.getenv().get("ALIYUN_AK_ID");
String secret = System.getenv().get("ALIYUN_AK_SECRET");
String url = System.getenv().getOrDefault("NLS_GATEWAY_URL", "wss://nls-gateway-cn-shanghai.aliyuncs.com/ws/v1");
SpeechSynthesizerDemo demo = new SpeechSynthesizerDemo(appKey, id, secret, url);
demo.process();
demo.shutdown();
}
}