全部产品
云市场

Java SDK 2.0

更新时间:2019-11-15 16:11:45

提示:

  • 在使用SDK之前,请先确保已阅读了接口说明文档
  • 请从下方链接下载最新示例Demo
  • 请注意需要更新SDK到最新版本(长文本语音合成功能要求SDK版本在2.1.1及以上)

下载安装

可从maven 服务器下载最新版本SDK:

  1. <dependency>
  2. <groupId>com.alibaba.nls</groupId>
  3. <artifactId>nls-sdk-tts</artifactId>
  4. <version>2.1.1</version>
  5. </dependency>

使用方式参见下面代码示例。Demo 源码下载链接

demo 解压后,在pom 目录运行mvn package ,会在target目录生成可执行jarnls-example-long-tts-2.0.0-jar-with-dependencies.jar将此jar拷贝到目标服务器,可用于快速验证及压测服务。

服务验证

java -cp nls-example-long-tts-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechSynthesizerDemo并按提示提供相应参数,运行后在命令执行目录生成logs/nls.log

服务压测

java -jar nls-example-long-tts-2.0.0-jar-with-dependencies.jar并按提示提供相应参数,其中阿里云服务url参数为: wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1 ,并发数根据用户已购买并发谨慎选择。

温馨提示:自行压测超过2并发会产生费用。

关键接口

  • NlsClient:语音处理client,相当于所有语音相关处理类的factory,全局创建一个实例即可。线程安全。
  • SpeechSynthesizer:语音合成处理类,设置请求参数,发送请求。非线程安全。
  • SpeechSynthesizerListener:语音合成监听类,监听返回结果。非线程安全。有如下两个抽象方法需要实现:
    1. /**
    2. * 接收语音合成二进制数据
    3. */
    4. abstract public void onMessage(ByteBuffer message);
    5. /**
    6. * 语音合成结束事件通知
    7. */
    8. abstract public void onComplete(SpeechSynthesizerResponse response);

    SDK 调用注意事项

  1. NlsClient对象创建一次可以重复使用,每次创建消耗性能。NlsClient使用了netty的框架,创建时比较消耗时间和资源,但创建之后可以重复利用。建议调用程序将NlsClient的创建和关闭与程序本身的生命周期结合。
  2. SpeechSynthesizer对象不能重复使用,一个语音合成任务对应一个SpeechSynthesizer对象。例如有N个文本需要语音合成,则要进行N次语音合成任务,创建N个SpeechSynthesizer对象。
  3. 实现的SpeechSynthesizerListener对象和SpeechSynthesizer对象是一一对应的,不能将一个SpeechSynthesizerListener对象设置到多个SpeechSynthesizer对象中,否则不能区分是哪个语音合成任务。
  4. Java SDK依赖了Netty网络库,版本需设置为4.1.17.Final及以上。如果您的应用中依赖了Netty,请确保版本符合要求。

代码示例

说明1:Demo中使用了SDK内置的默认语音合成服务的外网访问URL,如果您使用阿里云上海ECS并想使用内网访问URL,则在创建NlsClient对象时,设置内网访问的URL:

  1. client = new NlsClient("ws://nls-gateway.cn-shanghai-internal.aliyuncs.com/ws/v1", accessToken);

说明2:Demo中将合成的音频保存在了文件中,如果您需要播放音频且对实时性要求较高,建议使用流式播放,即边接收语音数据边播放,减少延时。

示例:

  1. package com.alibaba.nls.client;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.nio.ByteBuffer;
  6. import com.alibaba.nls.client.protocol.NlsClient;
  7. import com.alibaba.nls.client.protocol.OutputFormatEnum;
  8. import com.alibaba.nls.client.protocol.SampleRateEnum;
  9. import com.alibaba.nls.client.protocol.tts.SpeechSynthesizer;
  10. import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerListener;
  11. import com.alibaba.nls.client.protocol.tts.SpeechSynthesizerResponse;
  12. import org.slf4j.Logger;
  13. import org.slf4j.LoggerFactory;
  14. /**
  15. * 此示例演示了
  16. * 长文本语音合成API调用(setLongText)
  17. * 流式合成TTS
  18. * 首包延迟计算
  19. * (仅作演示,需用户根据实际情况实现)
  20. *
  21. * 说明:这个示例和nls-example-tts下的SpeechSynthesizerLongTextDemo不完全相同,长文本语音合成是单独的产品功能,是将一长串文本直接发送给服务端去合成;
  22. * 而SpeechSynthesizerLongTextDemo演示的是将一长串文本在调用方处切割然后分段调用语音合成接口
  23. */
  24. public class SpeechLongSynthesizerDemo {
  25. private static final Logger logger = LoggerFactory.getLogger(SpeechLongSynthesizerDemo.class);
  26. private static long startTime;
  27. private String appKey;
  28. NlsClient client;
  29. public SpeechLongSynthesizerDemo(String appKey, String token, String url) {
  30. this.appKey = appKey;
  31. //重要提示 创建NlsClient实例,应用全局创建一个即可,生命周期可和整个应用保持一致,默认服务地址为阿里云线上服务地址
  32. if(url.isEmpty()) {
  33. client = new NlsClient(token);
  34. } else {
  35. client = new NlsClient(url, token);
  36. }
  37. }
  38. private static SpeechSynthesizerListener getSynthesizerListener() {
  39. SpeechSynthesizerListener listener = null;
  40. try {
  41. listener = new SpeechSynthesizerListener() {
  42. File f=new File("ttsForLongText.wav");
  43. FileOutputStream fout = new FileOutputStream(f);
  44. private boolean firstRecvBinary = true;
  45. //语音合成结束
  46. @Override
  47. public void onComplete(SpeechSynthesizerResponse response) {
  48. // 当onComplete时表示所有TTS数据已经接收完成,因此这个是整个合成延迟,该延迟可能较大,未必满足实时场景
  49. System.out.println("name: " + response.getName() + ", status: " + response.getStatus()+", output file :"+f.getAbsolutePath());
  50. }
  51. //语音合成的语音二进制数据
  52. @Override
  53. public void onMessage(ByteBuffer message) {
  54. try {
  55. if(firstRecvBinary) {
  56. // 此处是计算首包语音流的延迟,收到第一包语音流时,即可以进行语音播放,以提升响应速度(特别是实时交互场景下)
  57. firstRecvBinary = false;
  58. long now = System.currentTimeMillis();
  59. logger.info("tts first latency : " + (now - SpeechLongSynthesizerDemo.startTime) + " ms");
  60. }
  61. byte[] bytesArray = new byte[message.remaining()];
  62. message.get(bytesArray, 0, bytesArray.length);
  63. //System.out.println("write array:" + bytesArray.length);
  64. fout.write(bytesArray);
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. @Override
  70. public void onFail(SpeechSynthesizerResponse response){
  71. // 重要提示: task_id很重要,是调用方和服务端通信的唯一ID标识,当遇到问题时,需要提供此task_id以便排查
  72. System.out.println(
  73. "task_id: " + response.getTaskId() +
  74. //状态码 20000000 表示识别成功
  75. ", status: " + response.getStatus() +
  76. //错误信息
  77. ", status_text: " + response.getStatusText());
  78. }
  79. };
  80. } catch (Exception e) {
  81. e.printStackTrace();
  82. }
  83. return listener;
  84. }
  85. public void process(String text) {
  86. SpeechSynthesizer synthesizer = null;
  87. try {
  88. //创建实例,建立连接
  89. synthesizer = new SpeechSynthesizer(client, getSynthesizerListener());
  90. synthesizer.setAppKey(appKey);
  91. //设置返回音频的编码格式
  92. synthesizer.setFormat(OutputFormatEnum.WAV);
  93. //设置返回音频的采样率
  94. synthesizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
  95. //发音人
  96. synthesizer.setVoice("siyue");
  97. //语调,范围是-500~500,可选,默认是0
  98. synthesizer.setPitchRate(0);
  99. //语速,范围是-500~500,默认是0
  100. synthesizer.setSpeechRate(0);
  101. //设置用于语音合成的文本
  102. // 重要提示: 这里调用的是setLongText接口(原语音合成接口是setText)
  103. synthesizer.setLongText(text);
  104. //此方法将以上参数设置序列化为json发送给服务端,并等待服务端确认
  105. long start = System.currentTimeMillis();
  106. synthesizer.start();
  107. logger.info("tts start latency " + (System.currentTimeMillis() - start) + " ms");
  108. SpeechLongSynthesizerDemo.startTime = System.currentTimeMillis();
  109. //等待语音合成结束
  110. synthesizer.waitForComplete();
  111. logger.info("tts stop latency " + (System.currentTimeMillis() - start) + " ms");
  112. } catch (Exception e) {
  113. e.printStackTrace();
  114. } finally {
  115. //关闭连接
  116. if (null != synthesizer) {
  117. synthesizer.close();
  118. }
  119. }
  120. }
  121. public void shutdown() {
  122. client.shutdown();
  123. }
  124. public static void main(String[] args) throws Exception {
  125. String appKey = "";
  126. String token = "填写你的token";
  127. // url 默认即可
  128. String url = "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1";
  129. if (args.length == 2) {
  130. appKey = args[0];
  131. token = args[1];
  132. } else if (args.length == 3) {
  133. appKey = args[0];
  134. token = args[1];
  135. url = args[2];
  136. } else {
  137. System.err.println("run error, need params(url is optional): " + "<app-key> <token> [url]");
  138. System.exit(-1);
  139. }
  140. String ttsTextLong = "百草堂与三味书屋 鲁迅 \n" +
  141. "我家的后面有一个很大的园,相传叫作百草园。现在是早已并屋子一起卖给朱文公的子孙了,连那最末次的相见也已经隔了七八年,其中似乎确凿只有一些野草;但那时却是我的乐园。\n" +
  142. "不必说碧绿的菜畦,光滑的石井栏,高大的皂荚树,紫红的桑葚;也不必说鸣蝉在树叶里长吟,肥胖的黄蜂伏在菜花上,轻捷的叫天子(云雀)忽然从草间直窜向云霄里去了。\n" +
  143. "单是周围的短短的泥墙根一带,就有无限趣味。油蛉在这里低唱,蟋蟀们在这里弹琴。翻开断砖来,有时会遇见蜈蚣;还有斑蝥,倘若用手指按住它的脊梁,便会啪的一声,\n" +
  144. "从后窍喷出一阵烟雾。何首乌藤和木莲藤缠络着,木莲有莲房一般的果实,何首乌有臃肿的根。有人说,何首乌根是有像人形的,吃了便可以成仙,我于是常常拔它起来,牵连不断地拔起来,\n" +
  145. "也曾因此弄坏了泥墙,却从来没有见过有一块根像人样! 如果不怕刺,还可以摘到覆盆子,像小珊瑚珠攒成的小球,又酸又甜,色味都比桑葚要好得远......";
  146. SpeechLongSynthesizerDemo demo = new SpeechLongSynthesizerDemo(appKey, token, url);
  147. demo.process(ttsTextLong);
  148. demo.shutdown();
  149. }
  150. }