语音合成(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和指定云服务enddpoint二选一即可)。
- 指定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(); } }