
# 实时语音合成
#### 前提条件
- 确保已按照[配置Java环境](https://support.huaweicloud.com/sdkreference-sis/sis_05_0041.html)配置完毕。
- 请参考[SDK（websocket）](https://support.huaweicloud.com/sdkreference-sis/sis_05_0004.html)获取最新版本SDK包。
 
#### 初始化Client
初始化RttsClient，其参数包括AuthInfo和SisConfig。
表1AuthInfo 
| 参数名称      | 是否必选 | 参数类型   | 描述                                                                                     |
|:---|:---|:---|:---|
| ak        | 是    | String | 用户的ak，可参考[AK/SK认证](https://support.huaweicloud.com/sdkreference-sis/sis_05_0003.html)。 |
| sk        | 是    | String | 用户的sk，可参考[AK/SK认证](https://support.huaweicloud.com/sdkreference-sis/sis_05_0003.html)。 |
| region    | 是    | String | 区域，如cn-north-4，参考[终端节点](https://support.huaweicloud.com/api-sis/sis_03_0004.html)。     |
| projectId | 是    | String | 项目ID，同region一一对应，参考[获取项目ID](https://support.huaweicloud.com/api-sis/sis_03_0008.html)。 |
| endpoint  | 否    | String | 终端节点，参考[终端节点](https://support.huaweicloud.com/api-sis/sis_03_0004.html)。               |
   
表2SisConfig 
| 参数名称                 | 是否必选 | 参数类型    | 描述                           |
|:---|:---|:---|:---|
| connectionTimeout    | 否    | Integer | 连接超时，默认10000，单位ms。           |
| readTimeout          | 否    | Integer | 读取超时，默认10000，单位ms。           |
| websocketWaitTimeout | 否    | Integer | websocket最大等待超时，默认20000，单位ms |
   
#### 请求参数
请求类为RttsRequest，详见[表3]。
 表3RttsRequest 
| 名称      | 参数类型   | 是否必选 | 说明                                                                             |
|:---|:---|:---|:---|
| command | String | 是    | 需设置为START，表示开始识别请求。                                                            |
| text    | String | 是    | 待合成的文本，详见[开始语音合成请求](https://support.huaweicloud.com/api-sis/sis_03_0115.html)。 |
| config  | Object | 否    | 配置信息。请参考[表 config数据结构]。                     |
   
 表4Config 
| 名称          | 参数类型    | 是否必选 | 说明                                                                                                                                                                       |
|:---|:---|:---|:---|
| audioFormat | String  | 否    | 语音格式头：pcm、alaw、ulaw、mp3。 默认：pcm                                                                                                            |
| sampleRate  | String  | 否    | 采样率：16000、8000。 默认：8000                                                                                                                   |
| property    | String  | 否    | 语音合成特征字符串，组成形式为{language}_{speaker}_{domain}，即"语种_人员标识_领域"，详见[开始语音合成请求](https://support.huaweicloud.com/api-sis/sis_03_0115.html)。  |
| speed       | Integer | 否    | 语速。 取值范围：-500\~500 默认值：0                                                                                     |
| pitch       | Integer | 否    | 音高。 取值范围：-500\~500 默认值：0                                                                                   |
| volume      | Integer | 否    | 音量。 取值范围：0\~100 默认值：50                                                                                     |
   
#### 响应参数
响应类为RttsDataResponse，详见[表5]。调用失败处理方法请参见[错误码](https://support.huaweicloud.com/api-sis/sis_03_0045.html)。
 表5RttsDataResponse 
| 参数名  | 是否必选 | 参数类型          | 说明           |
|:---|:---|:---|:---|
| data | 是    | Array of Byte | 音频文件的byte数组。 |
   
#### 代码示例
如下示例仅供参考，最新代码请前往[SDK（websocket）](https://support.huaweicloud.com/sdkreference-sis/sis_05_0004.html)章节获取并运行。
```
import com.cloud.sdk.util.StringUtils;
import com.huawei.sis.bean.AuthInfo;
import com.huawei.sis.bean.RttsListener;
import com.huawei.sis.bean.SisConfig;
import com.huawei.sis.bean.SisConstant;
import com.huawei.sis.bean.request.RttsRequest;
import com.huawei.sis.bean.response.RttsDataResponse;
import com.huawei.sis.bean.response.StateResponse;
import com.huawei.sis.client.RttsClient;
import com.huawei.sis.util.JsonUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
 * 实时语音合成Demo
 *
 * Copyright 2021 Huawei Technologies Co.,Ltd.
 */
public class RttsDemo {
  // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全；
  // 本示例以ak和sk保存在环境变量中来实现身份验证为例，运行本示例前请先在本地环境中设置环境变量HUAWEICLOUD_SDK_AK和HUAWEICLOUD_SDK_SK。
  private String ak = System.getenv("HUAWEICLOUD_SDK_AK");
  private String sk = System.getenv("HUAWEICLOUD_SDK_SK");
  private String region = "";         // 区域，如cn-north-1、cn-north-4
  private String projectId = "";      // 项目id，在我的凭证查看。参考https://support.huaweicloud.com/api-sis/sis_03_0008.html
  private String text = "";            // 待合成的文本
  private String path = "";            // 合成音频存储的路径
  public static void main(String[] args) {
    RttsDemo rttsDemo = new RttsDemo();
    rttsDemo.process();
  }
  /**
   * 实时语音合成参数设置，所有参数设置均为可选，均有默认值。用户根据需求设置参数。
   */
  private RttsRequest getRttsRequest() {
    RttsRequest request = new RttsRequest();
    request.setCommand("START");
    // 设置待合成文本，文本长度1-500字
    request.setText(text);
    RttsRequest.Config config = new RttsRequest.Config();
    // 设置发音人属性，{language}_{speaker}_{domain}, 详见api文档
    config.setPorperty("chinese_xiaoyan_common");
    // 设置合成音频格式，默认pcm
    config.setAudioFormat("pcm");
    // 设置合成音频采样率，当前支持8000和16000，默认8000
    config.setSampleRate("8000");
    // 设置合成音频音量大小，取值0-100，默认50
    config.setVolume(50);
    // 设置合成音频音高大小，取值-500-500，默认0
    config.setPitch(0);
    // 设置合成音频语速大小，取值-500-500，默认0
    config.setSpeed(0);
    request.setConfig(config);
    return request;
  }
  /**
   * 定义config，所有参数可选，设置超时时间等。
   *
   * @return SisConfig
   */
  private SisConfig getConfig() {
    SisConfig config = new SisConfig();
    // 设置连接超时，默认10000ms
    config.setConnectionTimeout(SisConstant.DEFAULT_CONNECTION_TIMEOUT);
    // 设置读取超时，默认10000ms
    config.setReadTimeout(SisConstant.DEFAULT_READ_TIMEOUT);
    // 设置websocket等待超时时间，默认20000ms
    config.setWebsocketWaitTimeout(SisConstant.DEFAULT_WEBSOCKET_WAIT_TIME);
    // 设置代理, 一定要确保代理可用才启动此设置。 代理初始化也可用不加密的代理，new ProxyHostInfo(host, port);
    // ProxyHostInfo proxy = new ProxyHostInfo(host, port, username, password);
    // config.setProxy(proxy);
    return config;
  }
  private void printResponse(Object response) {
    try {
      System.out.println(JsonUtils.obj2Str(response, true));
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  /**
   * 实时语音转写SDK的工作流程
   * 1. RttsClient只能发送一次文本，如有多个文本需发送，需要多次新建RttsClient实例
   * 2. 实时语音合成会多次收到音频响应，默认格式为pcm。在demo中会把多次返回的结果拼接起来，存入文件中。
   * 3. 当服务端完成合成任务后，会返回end响应。
   */
  private void process() {
    // 1. 实现监听器接口RttsListener，用户自定义收到响应的处理逻辑。
    RttsListener rttsListener = new MyRttsListener(path);
    // 2. 初始化RttsClient,每个client只能发送一次text，如需发送多次text，需要建立多个client
    AuthInfo authInfo = new AuthInfo(ak, sk, region, projectId);
    RttsClient rttsClient = new RttsClient(authInfo, rttsListener, getConfig());
    // 3. 配置参数
    // audioFormat为支持格式、property为属性字符串，具体填写请详细参考api文档
    RttsRequest request = getRttsRequest();
    // 4. 发送待合成文本，等待结果
    try {
      rttsClient.synthesis(request);
      // 设置企业id, 可选
      // Map<String, String> headers = OKHttpClientUtils.getJsonHeaders();
      // headers.put(SisConstant.ENTERPRISE_PROJECT_ID_KEY, "your enterprise_id");
      // rttsClient.synthesis(headers, request);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  public class MyRttsListener implements RttsListener {
    private String path;
    private FileOutputStream fos = null;
    public MyRttsListener() {
      super();
    }
    public MyRttsListener(String path) {
      this.path = path;
    }
    @Override
    public void onTranscriptionResponse(RttsDataResponse rttsDataResponse) {
      System.out.println("receive binary data " + rttsDataResponse.getData().length);
      if (fos == null) {
        return;
      }
      try {
        fos.write(rttsDataResponse.getData());
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    @Override
    public void onTranscriptionBegin(StateResponse response) {
      printResponse(response);
      try {
        if (StringUtils.isNullOrEmpty(path)) {
          return;
        }
        File f = new File(path);
        fos = new FileOutputStream(f);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
    @Override
    public void onSTranscriptionEnd(StateResponse response) {
      printResponse(response);
      close();
    }
    @Override
    public void onTranscriptionFail(StateResponse response) {
      printResponse(response);
      close();
    }
    private void close() {
      if (fos == null) {
        return;
      }
      try {
        fos.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
}
```
