更新时间:2024-12-04 GMT+08:00
分享

语音合成(http版)

前提条件

  • 确保已经按照配置好Android开发环境。
  • 请参考SDK(websocket)获取最新版本SDK包。

初始化Client

初始化SisClient,详细信息如下。

  1. 配置客户端连接参数。
    • 默认配置
      // 使用默认配置
      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);
  2. 配置认证信息。

    配置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)

    认证参数说明:

  3. 初始化客户端(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是华为云各服务应用区域和各服务的终端节点,详情请查看 地区和终端节点

请求参数

  1. 请求类为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参考》中语音合成章节。

  2. 伪代码
    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,详见下表。调用失败处理方法请参见错误码

表2 RunTtsResponse

参数名

是否必选

参数类型

说明

trace_id

String

服务内部的令牌,可用于在日志中追溯具体流程,调用失败无此字段。

在某些错误情况下可能没有此令牌字符串。

result

Object

调用成功时为合成语音内容,请参考表3

调用失败时无此字段。

表3 Result

参数名

是否必选

参数类型

说明

data

String

合成后生成的语音数据,以Base64编码格式返回。用户如需生成音频,需要将Base64编码解码成byte数组,再保存为wav音频。

示例代码

如下示例仅供参考,最新代码请前往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();
	}
}

相关文档