语音合成(http版)
前提条件
- 确保已经按照配置好Android开发环境。
- 请参考SDK(websocket)获取最新版本SDK包。
初始化Client
初始化SisClient,详细信息如下。
- 配置客户端连接参数。
- 默认配置
// 使用默认配置 HttpConfig config = HttpConfig.getDefaultHttpConfig();
- 网络代理(可选)
// 根据需要配置网络代理,网络代理默认的协议为 `http` 协议 config.withProxyHost("proxy.huaweicloud.com") .withProxyPort(8080) .withProxyUsername("test") .withProxyPassword("test"); - 超时配置(可选)
// 默认连接超时时间为60秒,可根据需要调整 config.withTimeout(60);
- SSL配置(可选)
// 根据需要配置是否跳过SSL证书验证 config.withIgnoreSSLVerification(true);
- 默认配置
- 配置认证信息。
配置AK、SK、project_id信息。华为云通过AK识别用户的身份,通过SK对请求数据进行签名验证,用于确保请求的机密性、完整性和请求者身份的正确性。
- 使用永久AK和SK
BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withProjectId(projectId); - 使用临时AK和SK
BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withSecurityToken(securityToken) .withProjectId(projectId)
认证参数说明:
- 使用永久AK和SK
- 初始化客户端(region和指定云服务endpoint二选一即可)。
- 指定region方式(强烈推荐)
// 初始化客户端认证信息,使用当前客户端初始化方式可不填 projectId/domainId,以初始化 BasicCredentials 为例 BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk); // 初始化指定云服务的客户端 {Service}Client ,以初始化 Region 级服务SIS的 SisClient 为例 SisClient client = SisClient.newBuilder() .withHttpConfig(config) .withCredential(basicCredentials) .withRegion(SisRegion.valueOf("cn-north-4")) .build(); - 指定云服务endpoint方式(可选)
// 指定终端节点,以SIS服务北京四的 endpoint 为例 String endpoint = "https://sis-ext.cn-north-4.myhuaweicloud.com"; // 初始化客户端认证信息,需要填写相应 projectId/domainId,以初始化 BasicCredentials 为例 BasicCredentials basicCredentials = new BasicCredentials() .withAk(ak) .withSk(sk) .withProjectId(projectId); // 初始化指定云服务的客户端 {Service}Client ,以初始化 Region 级服务SIS的 CbsClient 为例 SisClient client = SisClient.newBuilder() .withHttpConfig(config) .withCredential(basicCredentials) .withEndpoint(endpoint) .build();endpoint是华为云各服务应用区域和各服务的终端节点,详情请查看 地区和终端节点。
- 指定region方式(强烈推荐)
请求参数
- 请求类为RunTtsRequest,其中包含参数类PostCustomTTSReq,该类包含两个参数text(待合成文本)和TtsConfig,详见TtsConfig。
表1 TtsConfig 参数名称
是否必选
参数类型
描述
audio_format
否
String
待合成的音频格式,可选mp3,wav等,默认wav。具体信息请参见《API参考》中语音合成章节。
pitch
否
Integer
音高,[-500,500] ,默认是0。
speed
否
Integer
语速,[-500,500] ,默认是0。
volume
否
Integer
音量,[0,100],默认是50。
sample_rate
否
String
采样率,支持“8000”、“16000”,默认“8000”。
property
否
String
特征字符串,{language}_{speaker}_{domain},默认chinese_xiaoqi_common。具体信息请参见《API参考》中语音合成章节。
- 伪代码
TtsConfig configbody = new TtsConfig(); configbody.setAudioFormat(TtsConfig.AudioFormatEnum.fromValue("wav")); configbody.setSampleRate(TtsConfig.SampleRateEnum.fromValue("8000")); configbody.setProperty(TtsConfig.PropertyEnum.fromValue("chinese_huaxiaomei_common")); RunTtsRequest request = new RunTtsRequest(); PostCustomTTSReq body = new PostCustomTTSReq(); body.withConfig(configbody); if (!StringUtils.isEmpty(text.getText().toString())) { body.withText(text.getText().toString()); } else { body.withText("请输入合成文本"); } request.withBody(body); return request;
响应参数
响应类为RunTtsResponse,详见下表。调用失败处理方法请参见错误码。
|
参数名 |
是否必选 |
参数类型 |
说明 |
|---|---|---|---|
|
trace_id |
是 |
String |
服务内部的令牌,可用于在日志中追溯具体流程,调用失败无此字段。 在某些错误情况下可能没有此令牌字符串。 |
|
result |
是 |
Object |
调用成功时为合成语音内容,请参考表3。 调用失败时无此字段。 |
示例代码
如下示例仅供参考,最新代码请前往SDK(websocket)章节获取并运行。
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
*/
package com.huaweicloud.sis.android.demo.tts;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.core.http.HttpConfig;
import com.huaweicloud.sdk.core.utils.StringUtils;
import com.huaweicloud.sdk.sis.v1.SisClient;
import com.huaweicloud.sdk.sis.v1.model.PostCustomTTSReq;
import com.huaweicloud.sdk.sis.v1.model.RunTtsRequest;
import com.huaweicloud.sdk.sis.v1.model.RunTtsResponse;
import com.huaweicloud.sdk.sis.v1.model.TtsConfig;
import com.huaweicloud.sdk.sis.v1.region.SisRegion;
import com.huaweicloud.sis.android.demo.R;
import com.huaweicloud.sis.android.demo.service.MediaPlayerService;
import com.huaweicloud.sis.android.demo.Config;
/**
* 功能描述
* 语音合成 http
*
* @since 2022-07-18
*/
public class SttsActivity extends AppCompatActivity {
private EditText text;
private TextView outResult;
private Button startSoundRecording;
private Button startPlay;
private Handler handler;
// 保存合成的base64字符串
private String base64Data;
// 合成音频路径
private String createFilePath;
// 客户端请求
private SisClient client;
private MediaPlayerService mediaPlayerService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stts);
}
@Override
protected void onStart() {
super.onStart();
initView();
initResoureces();
}
@Override
protected void onDestroy() {
mediaPlayerService.stopMyPlayer(createFilePath);
super.onDestroy();
}
// 初始化界面
private void initView() {
text = findViewById(R.id.input_text);
outResult = findViewById(R.id.out_result);
startSoundRecording = findViewById(R.id.start);
startPlay = findViewById(R.id.startplay);
startSoundRecording.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Runnable runnable = new Runnable() {
@Override
public void run() {
String sttsRequestText = getSttsResponse();
Message message = new Message();
Bundle mBundle = new Bundle();
mBundle.putString("result", sttsRequestText);
message.setData(mBundle);
handler.sendMessage(message);
}
};
new Thread(runnable).start();
}
});
startPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!StringUtils.isEmpty(base64Data)) {
createFilePath = mediaPlayerService.createAudioFile(getBaseContext(), "wav", base64Data);
mediaPlayerService.startPlay(createFilePath);
}
}
});
}
/**
* 初始化资源
*
* @return
*/
private void initResoureces() {
BasicCredentials auth = new BasicCredentials()
.withAk(this.getString(R.string.HUAWEICLOUD_SDK_AK))
.withSk(this.getString(R.string.HUAWEICLOUD_SDK_SK))
.withProjectId(Config.PROJECT_ID);
HttpConfig config = HttpConfig.getDefaultHttpConfig();
config.withIgnoreSSLVerification(true);
client = SisClient.newBuilder()
.withHttpConfig(config)
.withCredential(auth)
.withRegion(SisRegion.valueOf(Config.REGION))
.build();
handler = new Handler(getMainLooper()) {
@Override
public void handleMessage(@NonNull Message message) {
super.handleMessage(message);
switch (message.what) {
case 0:
Bundle bundle = message.getData();
String rstr = bundle.getString("result");
outResult.setText(rstr);
break;
default:
Log.e("Unexpected value: ", String.valueOf(message.what));
}
}
};
mediaPlayerService = new MediaPlayerService();
}
// 设置请求体
private RunTtsRequest getRunTtsRequest() {
TtsConfig configbody = new TtsConfig();
configbody.setAudioFormat(TtsConfig.AudioFormatEnum.fromValue("wav"));
configbody.setSampleRate(TtsConfig.SampleRateEnum.fromValue("8000"));
configbody.setProperty(TtsConfig.PropertyEnum.fromValue("chinese_huaxiaomei_common"));
RunTtsRequest request = new RunTtsRequest();
PostCustomTTSReq body = new PostCustomTTSReq();
body.withConfig(configbody);
if (!StringUtils.isEmpty(text.getText().toString())) {
body.withText(text.getText().toString());
} else {
body.withText("请输入合成文本");
}
request.withBody(body);
return request;
}
// 发送请求
private String getSttsResponse() {
RunTtsRequest request = getRunTtsRequest();
String ttsString = "";
try {
RunTtsResponse response = client.runTts(request);
if (response.getResult().getData() != null) {
base64Data = response.getResult().getData();
ttsString = "合成成功";
} else {
ttsString = "合成失败";
}
Log.i("info", ttsString);
} catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) {
Log.e("error", e.toString());
} catch (Exception e) {
Log.e("error", e.toString());
}
return ttsString;
}
@Override
protected void onPause() {
mediaPlayerService.stopMyPlayer(createFilePath);
super.onPause();
}
}