通过OpenAPI定制

个性化人声定制服务可以帮助您通过少量的录音,训练得到自己的声音模型,快速“克隆”个性化的声音,进而使用该声音讲故事、播天气、读小说、导航播报等。本文介绍如何通过OpenAPI定制个性化人声。

通过OpenAPI定制

您可以通过使用智能语音交互服务提供的OpenAPI,将个性化人声定制功能集成在您自己的产品当中。集成后,即可通过接口来实现声音定制的功能。

个性化人声定制的步骤

image

以智能语音交互实现的页面举例以上步骤(红框部分)。

image

OpenAPI概览

对应定制步骤

接口名称

参数

参数说明

返回结果示例

返回结果说明

备注

1

GetDemonstrationForCustomizedVoice

Scenario

场景,取值范围如下:

  • story:故事

  • interaction:交互

  • navigation:导航

{"HttpCode":200,"Data":[{"AudioId":1,"DemoAudio":"http://nls-cloud-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/portal/tts/text_audio/wave/tonghua/300001.wav?Expires=1663660477&OSSAccessKeyId=LTAIbiWMiTSg****&Signature=%2BmFQIWuhvn%2F7FSlhtUKEK%2FLkoHM%3D&response-content-disposition=attachment%3Bfilename%3Dportal%2Ftts%2Ftext_audio%2Fwave%2Ftonghua%2F300001.wav","Text":"希望我们大家都能像他一样。"},],"Success":true}

通过本接口来获取需要给用户朗读的文本及示例音频。

  • Text字段为需要用户朗读的文本。

  • DemoAudio字段为示例音频。

  • AudioId为该文本的序号,对应音频检测时需要传入的AduioRecordId字段。

您可以获取相关文案及音频地址进行缓存,再次使用为可选接口。

2

CustomizedVoiceAudioDetect

Scenario

场景,取值范围如下:

  • story:故事

  • interaction:交互

  • navigation:导航

{"HttpCode":200,"Data":{"reason":"","pass":true},"Success":true}

本接口用来检测用户的朗读是否有明显的发音错误、嘈杂的环境等。

  • pass字段表示该音频是否通过检测。

  • reason字段在音频未通过检测时会给出具体原因。

云端在进行完音频检测后,对于检测合格的音频会暂存在云端,供后续训练声音时使用,请勿省略该步骤。

VoiceName

您自定义的声音名称,不能和您其他的定制声音重名。支持15个字符以内的英文、汉字或数字。

RecordUrl

录音文件地址。

AudioRecordId

RecordUrl对应的音频序号,取值范围为[1,20]。例如故事场景下,用户朗读的“希望我们大家都能像他一样”这句话,对应序号为1。

3

SubmitCustomizedVoice

VoiceName

您自定义的声音名称,不能和您其他的定制声音重名。支持15个字符以内的英文、汉字或数字。

{"HttpCode":200,"Data":"1508592","Success":true}

提交合成,VoiceName需要与音频检测时传递至云端的一致,云端依赖此参数寻找暂存的音频进行训练。

Gender

性别,取值范围如下:

  • female:女性

  • male:男性

Scenario

场景,取值范围如下:

  • story:故事

  • interaction:交互

  • navigation:导航

4

ListCustomizedVoice

VoiceName

您在提交合成时自定义的声音名称。

{"HttpCode":200,"Data":[{"Status":"WAIT","StatusDesc":"WAIT","GmtCreate":"2022-09-19 17:27:46","Messages":["合成中,大约剩余29分钟"],"ProjectName":"个性化人声定制自动生成","AppKey":"5AwL7iBVbnF23XR4","Id":1508592,"ModelId":"voice-176bb8a","VoiceName":"Demo-1663579664914","Scenario":"story"}],"Success":true}

您可以在提交合成后,通过查询此接口的方式来检查是否合成完成,返回结果中的Status字段为合成状态,取值范围为:WAIT,合成中; SUCCESS,合成完成;FAILED,合成失败。当状态为合成失败时,您可以通过ErrorMessage字段获取失败的原因。

合成成功后,您可以通过ModelId字段作为voiceName调用克隆的声音模型

准备音频文件

音频格式要求

  • 支持的输入格式:单声道(mono)16bit采样位数音频,包括无压缩的PCM、WAV格式。

  • 音频采样率:16000 Hz、24000 Hz、48000 Hz。

音频保存

  • 音频文件的地址,需要是公网可以访问的URL,建议您使用OSS,通过加签授权或者开放Bucket的方式提供给API进行使用。

  • 您可以通过OSS的服务端签名后直传的方式,授权您的采集端,采集音频后直接将录音上传至OSS。

SDK

个性化人声定制的OpenAPI均通过阿里云CommonRequest进行调用,SDK可从如下文档中获取:

如果您无法使用上述语言提供的基础SDK进行调用,则可以参照RPC 调用机制自行构造HTTP请求进行调用。因自行构造HTTP请求涉及签名等复杂机制,强烈建议您尽量使用基础SDK进行调用。

OpenAPI调用基础参数

地域

调用参数

华东2(上海)

  • regionId="cn-shanghai"

  • endpointName="cn-shanghai"

  • domain="nls-measure.cn-shanghai.aliyuncs.com"

  • sysVersion="2019-09-05"

示例代码

调用接口前,需配置环境变量,通过环境变量读取访问凭证。智能语音交互的AccessKey ID和AccessKey Secret的环境变量名:ALIYUN_AKIDALIYUN_AKKEY

示例音频

为了方便您快速了解OpenAPI的调用流程,我们提供了如下示例音频供您运行示例代码使用,该音频为故事(story)场景。

1. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/viwf/1.wav
2. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dycw/2.wav
3. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dopl/3.wav
4. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/anfd/4.wav
5. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/cyoy/5.wav
6. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dsjw/6.wav
7. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/vevd/7.wav
8. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ulno/8.wav
9. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kwlw/9.wav
10. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lafu/10.wav
11. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/uozh/11.wav
12. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/gdpp/12.wav
13. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lisa/13.wav
14. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/bmvv/14.wav
15. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ijzx/15.wav
16. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kdla/16.wav
17. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/govf/17.wav
18. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kcid/18.wav
19. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/srdx/19.wav
20. https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/stol/20.wav

Java

相关依赖,请参见SDK核心依赖

package com.alibaba.nls.ptts;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;

public class PttsDemo {
    //域名
    private static final String DOMAIN = "nls-measure.cn-shanghai.aliyuncs.com";
    // API版本
    private static final String API_VERSION = "2019-09-05";

    private static IAcsClient client;

    static {
        // 创建DefaultAcsClient实例并初始化
        DefaultProfile profile = DefaultProfile.getProfile(
            "",
            System.getenv("ALIYUN_AKID"),
            System.getenv("ALIYUN_AKKEY"));
        client = new DefaultAcsClient(profile);
    }

    public static void main(String[] args) throws InterruptedException {
        //20句音频,此处为了方便演示接口的调用,提前准备好了音频的url,在您集成时,可以在用户录制的过程中,将音频进行存储
        String[] urls = {"viwf/1.wav", "dycw/2.wav", "dopl/3.wav", "anfd/4.wav", "cyoy/5.wav", "dsjw/6.wav",
            "vevd/7.wav", "ulno/8.wav", "kwlw/9.wav", "lafu/10.wav", "uozh/11.wav", "gdpp/12.wav", "lisa/13.wav",
            "bmvv/14.wav", "ijzx/15.wav", "kdla/16.wav", "govf/17.wav", "kcid/18.wav", "srdx/19.wav", "stol/20.wav"};

        //训练的基本信息,voiceName请替换成您自己的命名
        String voiceName = "示例voice";
        String scenario = "story";
        String gender = "female";

        //Step1: 获取需要朗读的文本
        CommonRequest getDemonstrationRequest = buildRequest("GetDemonstrationForCustomizedVoice");
        getDemonstrationRequest.putQueryParameter("Scenario", scenario);
        String getDemonstrationResponse = sendRequest(getDemonstrationRequest);
        System.out.println("|获取需要朗读的内容|response=" + getDemonstrationResponse);

        //Step2: 采集用户朗读的音频,进行音频检测
        for (int i = 1; i <= 20; i++) {
            String audioUrl = audioRecordUrlPrefix + urls[i - 1];
            CommonRequest audioDetectRequest = buildRequest("CustomizedVoiceAudioDetect");
            audioDetectRequest.putQueryParameter("Scenario", scenario);
            audioDetectRequest.putQueryParameter("VoiceName", voiceName);
            audioDetectRequest.putQueryParameter("RecordUrl", audioUrl);
            audioDetectRequest.putQueryParameter("AudioRecordId", String.valueOf(i));
            String audioDetectResponse = sendRequest(audioDetectRequest);
            System.out.println("|音频检测|[" + i + "]response=" + audioDetectResponse);
        }

        //Step3: 20句音频检测完成后,提交训练
        CommonRequest submitTrainRequest = buildRequest("SubmitCustomizedVoice");
        submitTrainRequest.putQueryParameter("VoiceName", voiceName);
        submitTrainRequest.putQueryParameter("Gender", gender);
        submitTrainRequest.putQueryParameter("Scenario", scenario);

        String submitTrainResponse = sendRequest(submitTrainRequest);
        System.out.println("|提交训练|response=" + submitTrainResponse);

        //Step4: 轮询训练结果

        CommonRequest queryTrainResultRequest = buildRequest("ListCustomizedVoice");
        queryTrainResultRequest.putQueryParameter("VoiceName", voiceName);
        String queryTrainResultResponse = sendRequest(queryTrainResultRequest);
        System.out.println("|查询训练结果|response=" + queryTrainResultResponse);
    }

    private static String audioRecordUrlPrefix
        = "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/";

    private static CommonRequest buildRequest(String popApiName) {
        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain(DOMAIN);
        request.setSysVersion(API_VERSION);
        request.setSysAction(popApiName);
        request.setSysProtocol(ProtocolType.HTTPS);
        return request;
    }

    private static String sendRequest(CommonRequest request) {
        try {
            CommonResponse response = client.getCommonResponse(request);
            return response.getData();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Python

依赖安装方式

pip install aliyun-python-sdk-core

代码

import os

from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.http import method_type
from aliyunsdkcore.request import CommonRequest

# api基础信息
client = AcsClient(os.environ.get('ALIYUN_AKID'),
                   os.environ.get('ALIYUN_AKKEY'))
domain = 'nls-measure.cn-shanghai.aliyuncs.com'
version = '2019-09-05'

# voice训练基础信息
scenario = 'story'
gender = 'female'
voice_name = '示例voice'

# 训练用音频示例,请替换为您自己的音频
audio_record_prefix = 'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/'
audio_records = ['viwf/1.wav', 'dycw/2.wav', 'dopl/3.wav', 'anfd/4.wav', 'cyoy/5.wav', 'dsjw/6.wav', 'vevd/7.wav',
                 'ulno/8.wav', 'kwlw/9.wav', 'lafu/10.wav', 'uozh/11.wav', 'gdpp/12.wav', 'lisa/13.wav', 'bmvv/14.wav',
                 'ijzx/15.wav', 'kdla/16.wav', 'govf/17.wav', 'kcid/18.wav', 'srdx/19.wav', 'stol/20.wav']


def build_request(api_name):
    request = CommonRequest()
    request.set_domain('nls-measure.cn-shanghai.aliyuncs.com')
    request.set_version('2019-09-05')
    request.set_action_name(api_name)
    request.set_method(method_type.POST)
    return request


if __name__ == '__main__':
    # step1: 获取需要朗读的文本
    get_demonstration_request = build_request(
        'GetDemonstrationForCustomizedVoice')
    get_demonstration_request.add_query_param('Scenario', scenario)
    get_demonstration_response = client.do_action_with_exception(
        get_demonstration_request)
    print(get_demonstration_response)

    # step2:声音检测
    for audio_record_id in range(1, 21):
        audio_record_url = audio_record_prefix + \
            audio_records[audio_record_id-1]
        audio_detect_request = build_request('CustomizedVoiceAudioDetect')
        audio_detect_request.add_query_param('Scenario', scenario)
        audio_detect_request.add_query_param('VoiceName', voice_name)
        audio_detect_request.add_query_param('RecordUrl', audio_record_url)
        audio_detect_request.add_query_param('AudioRecordId', audio_record_id)

        audio_detect_response = client.do_action_with_exception(
            audio_detect_request)
        print(audio_record_id)
        print(audio_detect_response)

    # step3: 提交训练
    submit_train_request = build_request('SubmitCustomizedVoice')
    submit_train_request.add_query_param('Scenario', scenario)
    submit_train_request.add_query_param('VoiceName', voice_name)
    submit_train_request.add_query_param('Gender', gender)

    submit_train_response = client.do_action_with_exception(
        submit_train_request)
    print(submit_train_response)

    # step4: 查询训练结果
    query_train_result_request = build_request('ListCustomizedVoice')
    query_train_result_request.add_query_param('VoiceName', voice_name)

    query_train_result_response = client.do_action_with_exception(
        query_train_result_request)
    print(query_train_result_response)

Go

依赖安装方式

go get -u github.com/aliyun/alibaba-cloud-sdk-go/sdk

代码

package main

import (
    "os"
	"fmt"
	"strconv"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
)

func main() {
	//初始化客户端
	client, err := sdk.NewClientWithAccessKey("cn-hangzhou", os.Getenv("ALIYUN_AKID"), os.Getenv("ALIYUN_AKKEY"))
	if err != nil {
		panic(err)
	}
	//API信息
	const DOMAIN string = "nls-measure.cn-shanghai.aliyuncs.com"
	const API_VERSION string = "2019-09-05"

	// voice训练基本信息
	var scenario = "story"
	var gender = "female"
	var voiceName = "示例voice"

	//
	var audioRecords = [20]string{
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/viwf/1.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dycw/2.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dopl/3.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/anfd/4.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/cyoy/5.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dsjw/6.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/vevd/7.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ulno/8.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kwlw/9.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lafu/10.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/uozh/11.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/gdpp/12.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lisa/13.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/bmvv/14.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ijzx/15.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kdla/16.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/govf/17.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kcid/18.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/srdx/19.wav",
		"https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/stol/20.wav",
	}

	// step1: 获取需要朗读的文本
	getDemonstrationRequest := requests.NewCommonRequest()
	getDemonstrationRequest.Domain = DOMAIN
	getDemonstrationRequest.Version = API_VERSION
	getDemonstrationRequest.ApiName = "GetDemonstrationForCustomizedVoice"
	getDemonstrationRequest.Method = "POST"

	getDemonstrationRequest.QueryParams["Scenario"] = scenario

	postResponse, err := client.ProcessCommonRequest(getDemonstrationRequest)
	if err != nil {
		panic(err)
	}
	postResponseContent := postResponse.GetHttpContentString()
	fmt.Println(postResponseContent)

	// step2:声音检测
	for i := 1; i <= 20; i++ {
		audioDetectRequest := requests.NewCommonRequest()
		audioDetectRequest.Domain = DOMAIN
		audioDetectRequest.Version = API_VERSION
		audioDetectRequest.ApiName = "CustomizedVoiceAudioDetect"
		audioDetectRequest.Method = "POST"

		audioDetectRequest.QueryParams["Scenario"] = scenario
		audioDetectRequest.QueryParams["VoiceName"] = voiceName
		audioDetectRequest.QueryParams["RecordUrl"] = audioRecords[i-1]
		audioDetectRequest.QueryParams["AudioRecordId"] = strconv.Itoa(i)

		audioDetectResponse, err := client.ProcessCommonRequest(audioDetectRequest)
		if err != nil {
			panic(err)
		}
		postResponseContent := audioDetectResponse.GetHttpContentString()
		fmt.Println(postResponseContent)
	}

	// step3: 提交训练
	submitTrainRequest := requests.NewCommonRequest()
	submitTrainRequest.Domain = DOMAIN
	submitTrainRequest.Version = API_VERSION
	submitTrainRequest.ApiName = "SubmitCustomizedVoice"
	submitTrainRequest.Method = "POST"

	submitTrainRequest.QueryParams["Scenario"] = scenario
	submitTrainRequest.QueryParams["VoiceName"] = voiceName
	submitTrainRequest.QueryParams["Gender"] = gender

	submitTrainResponse, err := client.ProcessCommonRequest(submitTrainRequest)
	if err != nil {
		panic(err)
	}
	submitTrainResponseContent := submitTrainResponse.GetHttpContentString()
	fmt.Println(submitTrainResponseContent)

	// step4: 查询训练结果
	queryTrainRequest := requests.NewCommonRequest()
	queryTrainRequest.Domain = DOMAIN
	queryTrainRequest.Version = API_VERSION
	queryTrainRequest.ApiName = "ListCustomizedVoice"
	queryTrainRequest.Method = "POST"

	queryTrainRequest.QueryParams["VoiceName"] = voiceName

	queryTrainResponse, err := client.ProcessCommonRequest(queryTrainRequest)
	if err != nil {
		panic(err)
	}
	queryTrainResponseContent := queryTrainResponse.GetHttpContentString()
	fmt.Println(queryTrainResponseContent)
}

PHP

依赖安装方式,请参见SDK核心依赖

<?php
  require __DIR__ . '/vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;

// 创建一个客户端并链式调用设置其它选项
AlibabaCloud::accessKeyClient(getenv('ALIYUN_AKID'), getenv('ALIYUN_AKKEY'))
  ->regionId('cn-shanghai') // 设置客户端区域,使用该客户端且没有单独设置的请求都使用此设置
  ->asGlobalClient();

# 训练用音频示例,请替换为您自己的音频
$audio_record_urls = array(
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/viwf/1.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dycw/2.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dopl/3.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/anfd/4.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/cyoy/5.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dsjw/6.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/vevd/7.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ulno/8.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kwlw/9.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lafu/10.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/uozh/11.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/gdpp/12.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lisa/13.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/bmvv/14.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ijzx/15.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kdla/16.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/govf/17.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kcid/18.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/srdx/19.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/stol/20.wav'
);

# voice训练基础信息
$scenario = 'story';
$gender = 'female';
$voice_name = '示例voice';

try {
  # step1: 获取需要朗读的文本
  $get_demonstration_request = AlibabaCloud::rpc()
    ->product('nls-cloud-measure')
    ->version('2019-09-05')
    ->action('GetDemonstrationForCustomizedVoice')
    ->host('nls-measure.cn-shanghai.aliyuncs.com')
    ->method('POST')
    ->options([
              'query' => [
              'Scenario' => $scenario,
              ],
              ])
              ->request();
              print_r($get_demonstration_request->toArray());

              # step2:声音检测
              for ($i = 1; $i <= 20; $i++) {
              $audio_detect_request = AlibabaCloud::rpc()
              ->product('nls-cloud-measure')
              ->version('2019-09-05')
              ->action('CustomizedVoiceAudioDetect')
              ->host('nls-measure.cn-shanghai.aliyuncs.com')
              ->method('POST')
              ->options([
              'query' => [
              'Scenario' => $scenario,
              'VoiceName' => $voice_name,
              'RecordUrl' => $audio_record_urls[$i-1],
              'AudioRecordId' => $i,
              ],
              ])->request();
              print_r($audio_detect_request->toArray());
              }

              # step3: 提交训练
              $submit_train_request = AlibabaCloud::rpc()
              ->product('nls-cloud-measure')
              ->version('2019-09-05')
              ->action('SubmitCustomizedVoice')
              ->host('nls-measure.cn-shanghai.aliyuncs.com')
              ->method('POST')
              ->options([
              'query' => [
              'Scenario' => $scenario,
              'VoiceName' => $voice_name,
              'Gender' => $gender
              ],
              ])->request();
              print_r($submit_train_request->toArray());

              # step4: 查询训练结果
              $query_train_result_request = AlibabaCloud::rpc()
              ->product('nls-cloud-measure')
              ->version('2019-09-05')
              ->action('ListCustomizedVoice')
              ->host('nls-measure.cn-shanghai.aliyuncs.com')
              ->method('POST')
              ->options([
              'query' => [
              'VoiceName' => $voice_name,
              ],
              ])->request();
              print_r($query_train_result_request->toArray());

              } catch (ClientException $exception) {
              print_r($exception->getErrorMessage());
              } catch (ServerException $exception) {
              print_r($exception->getErrorMessage());
              }
              ?>

Node.js

依赖安装方式

var RPCClient = require('@alicloud/pop-core');

var client = new RPCClient({
  accessKeyId: process.env.ALIYUN_AKID,
  accessKeySecret: process.env.ALIYUN_AKKEY,
  endpoint: 'https://nls-measure.cn-shanghai.aliyuncs.com',
  apiVersion: '2019-09-05'
});

//  voice训练基础信息,  voiceName请设置成您自己的名称
var scenario = 'story', gender = 'female', voiceName = '示例voice'

// 训练用音频示例,请替换为您自己的音频
var audioRecordUrls = [
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/viwf/1.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dycw/2.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dopl/3.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/anfd/4.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/cyoy/5.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/dsjw/6.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/vevd/7.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ulno/8.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kwlw/9.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lafu/10.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/uozh/11.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/gdpp/12.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/lisa/13.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/bmvv/14.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/ijzx/15.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kdla/16.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/govf/17.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/kcid/18.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/srdx/19.wav',
  'https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20221118/stol/20.wav'];


(async function () {
  // step1: 获取需要朗读的文本
  var getDemonstrationForCustomizedVoiceParam = {
    Scenario: scenario
  }
  const response1 = await client.request("GetDemonstrationForCustomizedVoice", getDemonstrationForCustomizedVoiceParam, { method: 'POST' })
  console.log('step1', JSON.stringify(response1))

  // step2: 声音检测
  for (var i = 1; i <= 20; i++) {
    var audioDetectParam = {
      Scenario: scenario,
      VoiceName: voiceName,
      RecordUrl: audioRecordUrls[i - 1],
      AudioRecordId: i
    }
      const response2 = await client.request("CustomizedVoiceAudioDetect", audioDetectParam, { method: 'POST' })
      console.log(`声音检测-${i}`, JSON.stringify(response2))
      }
      // step3: 提交训练
      var submitTrainParam = {
      Scenario: scenario,
      VoiceName: voiceName,
      Gender: gender
      }
      const response3 = await client.request("SubmitCustomizedVoice", submitTrainParam, { method: 'POST' })
      console.log('step3', JSON.stringify(response3))

      //  step4: 查询训练结果
      var queryTrainResultParam = {
      VoiceName: voiceName
      }
      const response4 = await client.request("ListCustomizedVoice", queryTrainResultParam, { method: 'POST' })
      console.log('step4', JSON.stringify(response4))
      }())

错误码列表

当发生错误时,返回值中的Success字段为false,ErrorCode为此时的错误码,ErrorMessage为错误信息。

ErrorCode

ErrorMessage

处理方式

100001

Service temporarily unavailable

服务端错误,此类错误您可以提交工单,发送ResuestId,由工程师进行定位排查。

100002

Illegal record url

错误的音频文件地址,请确保您传递给OpenAPI的音频文件公网可以访问,且为正确的音频。

100004

Missing record for train

用于训练的音频数据不完整,请确保20句音频都完成音频检测后再提交训练。

100009

会包含具体错误的信息,一般为业务错误等

根据错误信息修正您的代码。

100010

您尚未开通智能语音交互服务,无法使用该功能

使用接口前,请先开通智能语音交互服务。

100012

参数错误,会包含具体的参数错误原因

根据提示修正您的参数。

定制成功后进行语音合成

通过个性化人声定制合成了您想要的声音后,可以试用控制台进行文本转语音,也可以通过接口进行,请您检查以下调用条件是否具备:

  • 确保您已经定制的声音为训练成功状态(可以在控制台试听)。

  • 通过智能语音交互控制台的服务开通与管理页,确认您需要使用的接口的语音合成服务处于试用商用版状态。

    重要

    商用版是付费的,且从商用版切回试用版后会调用不通。

  • (可选)可以调通阿里云语音合成接口接口的其他音色。

如何通过代码调用控制台中定制的音色

  1. 定制完成后,推荐您使用语音合成接口调用该声音。更多接口文档,请参见接口说明

  2. 调用定制声音需要在语音合成中将个性化人声的模型调用ID(在阿里云智能语音交互控制台,单击音色试听,在详情页中获取,如下图)填入voice参数,示例代码如下。

    synthesizer.setVoice("${模型调用ID}");

    13

    您也可以通过实时/异步长文本语音合成来调用,方法同上。更多接口文档,请参见长文本语音合成

  3. 试用期过后,使用方式请见下表。

    使用声音合成文本的方式

    需要开通服务

    开通位置

    开通方法

    文本转语音方式

    控制台界面试用14

    新开通服务的3个月内,无需开通,免费试听。

    免费试听

    免费试听

    界面操作,下载音频。15

    控制台界面试用16

    语音合成

    登录阿里云智能语音交互控制台,选择服务管理与开通语音合成,单击升级商用版

    语音合成区域,选择商用,商用后为付费使用服务。6

更多调用相关信息,请参见下表。

调用方式

调用服务

注意事项

操作步骤

说明

通过控制台调用语音合成

语音合成

若您单次合成内容小于等于300字,请选择语音合成,控制台界面使用文字转语音,仅支持单次300字以内合成。

登录阿里云智能语音交互控制台,选择服务管理与开通语音合成,单击升级商用版

语音合成区域,选择商用,商用后为付费使用服务。6

更多接口内容,请参见接口说明

通过API调用语音合成

通过SDK调用语音合成

通过API调用异步长文本语音合成

长文本语音合成

若您合成内容大于300字,选择长文本语音合成,仅支持SDK或API接口使用。

登录阿里云智能语音交互控制台,选择服务管理与开通长文本语音合成,单击升级商用版

长文本语音合成区域,选择商用,商用后为付费使用服务。7

更多异步长文本语音合成接口内容,请参见接口说明

通过SDK调用长文本语音合成

更多实时长文本语音合成接口内容,请参见接口说明