logo
电话400 898 2016
预约试用
开放平台
En
尊敬的开发者,您好! 标贝科技的开发文档已更换新的地址,旧版文档地址将会在2023年12月31日下线, 给您带来不便,敬请谅解! 立即查看
产品简介 产品简介
基本概念 基本概念
平台新手指引 平台新手指引
计价模式 计价模式
开发者文档下拉
开放平台计价
定制服务计价
获取访问令牌 获取访问令牌
语音合成 语音合成
开发者文档下拉
接口说明
发音人列表
短文本合成 开发者文档下拉
Android SDK
iOS SDK
C++(Linux) SDK
RESTful API
Websocket API
长文本合成 开发者文档下拉
长文本合成RESTful API
长文本合成Websocket API
离线合成 开发者文档下拉
模型文件说明
离线合成(普通版) Android SDK
离线合成(普通版) iOS SDK
离线合成(精品版) Android SDK
离线合成(精品版) iOS SDK
XML标签
SSML标签
语音合成时间戳功能
语音识别 语音识别
开发者文档下拉
音频格式说明
一句话识别 开发者文档下拉
RESTful API
Websocket API
Android SDK
iOS SDK
实时长语音识别 开发者文档下拉
Websocket API
Android SDK
iOS SDK
录音文件识别 开发者文档下拉
RESTful API
自学习工具 开发者文档下拉
热词
个性化模型
声音复刻 声音复刻
开发者文档下拉
定制模型 开发者文档下拉
RESTful API
Android SDK
iOS SDK
定制声音合成 开发者文档下拉
短文本合成RESTful API
长文本合成Websocket API
声音转换 声音转换
开发者文档下拉
发音人列表
Websocket API
Android SDK
iOS SDK
离线声音转换 离线声音转换
开发者文档下拉
发音人列表
Android SDK
iOS SDK
声纹识别 声纹识别
开发者文档下拉
RESTful API
声音理解 声音理解
开发者文档下拉
RESTful API
协议规则 协议规则
开发者文档下拉
平台服务协议
平台通用规则
法律声明及隐私政策
服务等级协议SLA
常见问题 常见问题
开发者文档下拉
语音合成
语音识别

长文本合成RESTful API

功能介绍

长文本语音合成API满足用户希望一次性合成较长文本的需求,例如一篇新闻稿,一篇短篇小说。长文本合成API采用异步方式支持调用,提供两种获取数据的方式:轮询方式和回调方式。如果采用回调方式,用户调用接口上传文本的同时需要额外提供一个回调url,当文本上传完成后合成服务立刻响应,释放连接,当完成合成后通过事先提供的回调url将合成结果(音频链接)返回。用户亦可选择通过轮询作品合成结果接口来获取音频链接(轮训频率不应过高,建议10秒或更长时间执行一次即可)。

长文本语音合成采用异步调用(非实时),文本上传成功后进入等待队列,合成成功后通过回调的方式返回音频,返回结果时间受文本长度以及排队任务量的影响。如遇合成耗时比平时延长,大概率表示当前时间段出现合成高峰,请耐心等待。

参数设置

  • 支持设置合成音频的格式: wav, pcm, mp3
  • 支持设置合成音频的采样率:8000Hz、16000Hz、24000Hz
  • 支持设置多种发音人
  • 支持设置音量、语速、语调
  • 支持返回时间戳信息
  • 支持设置多种语言:中文(zh),英文(eng),粤语(cat),四川话(sch),天津话(tjh),台湾话(tai),韩语(kr),巴葡语(bra),日语(jp),西班牙西语(ESP),墨西哥西语(MEX),维吾尔语(UYG)

使用方法

1. 创建账号和应用,详见平台新手指引,通过标贝开放平台/应用/服务获取client_id,client_secret

2. 发送请求获取access_token,详见获取访问令牌

3. 发送请求:发送语音合成请求,具体参数详见请求参数

4. 接收回调请求(可选):语音生成后,会将生成音频的下载地址发送到回到地址,具体详见回调说明。

5.主动轮询作品合成结果接口(可选):根据workId查询对应作品的合成状态和合成结果,具体详见 轮询说明

服务地址

访问类型 说明 URL Host
外网访问 支持全部音色及语言
只支持POST调用
https://openapi.data-baker.com/asynctts/synthesis/work openapi.data-baker.com
外网访问 根据workId主动查询合成结果
只支持GET调用
https://openapi.data-baker.com/asynctts/synthesis/query openapi.data-baker.com

交互流程

提供两种获取音频链接的方式:
1)通过提供回调Url的方式,由服务端在合成任务完成后,推送音频数据

2)通过轮询的方式,查询合成任务对应的音频数据,轮询频率建议为10秒一次

请求参数

长文本语音合成的请求参数如下表所示。发送HTTPS请求时需要将这些参数设置到请求体(Body)中。

参数名称 参数格式 是否必填 说明
access_token String 通过client_id,client_secret调用授权服务获得见获取访问令牌
text String 需要合成的文本(UTF8编码)支持一次性上传不超过10万个字节。
voiceName String 设置发音人声音名称,详见 发音人列表
notifyUrl String 该地址用于接收合成结果,该地址必须为外网可访问的url,不能携带参数。
如果选择轮询方式获取音频数据,此参数可以不传。
speed String 设置播放的语速,在0~9之间(支持一位浮点值),不传时默认为5
volume String 设置语音的音量,在0~9之间(只支持整型值),不传时 默认值为5
audiotype Integer 设置音频格式,可不填
audiotype=3 :默认值 返回mp3格式
audiotype=4 :返回pcm格式
audiotype=6 :返回wav格式
sampleRate Integer 设置采样率,可不填,
普通音色默认16000 Hz,
电话信道音色默认8000Hz,
目前可选参数值:8000、16000、24000.
pitch Integer 设置语音的音调,取值0-9,不传时默认为5中语调
language String 合成请求文本的语言:
ZH(中文和中英混,默认值)
ENG(纯英文,中文部分不会合成)
CAT(粤语)
SCH(四川话)
TJH(天津话)
TAI(台湾话)
KR(韩语)
BRA(巴葡语)
JP(日语)
ESP(西班牙西语)
MEX(墨西哥西语)
UYG(维吾尔语)
spectrum Integer 频谱,取值范围0~20;不传时默认为不调整频谱;
值为0代表使用配置文件tts_attention.conf中spec_adjust_d的值;
1代表不调整频谱;
1以上的值代表高频能量增加幅度,值越大声音的高频部分增强越多,听起来更亮和尖细
spectrum_8k Integer 低频部分频谱,取值范围0~20;不传时默认为0,仅针对8K音频频谱的调整。
silence string 设置标点符号静音时长:
'0':默认值
'1':句中标点停顿较短,适合直播、配音解说等场景
'2':句中标点停顿较长,适合朗诵、教学等场景

请求示例

curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json'
 '{ \
   "access_token": "b939b1b7-624b-4bee-b249-c1870576297c", \
   "audiotype": "3", \
   "notifyUrl": "https://openapi.data-baker.com/asynctts/synthesis/notify", \
   "speed": "5", \
   "text": "请求数据", \
   "voiceName": "Jiaojiao", \
   "volume": "5" \
 }' 'https://openapi.data-baker.com/asynctts/synthesis/work'

Python示例代码

代码地址:Github

Python3示例:

import argparse
import requests
import json
import time


# 获取access_token用于鉴权
def get_access_token(client_secret, client_id):
    grant_type = "client_credentials"
    url = "https://openapi.data-baker.com/oauth/2.0/token?grant_type={}&client_secret={}&client_id={}".format(
        grant_type, client_secret, client_id)
    response = requests.post(url)
    access_token = json.loads(response.text).get('access_token')

    return access_token


# 创建任务,发送文字
def send_text(data):
    url = "https://openapi.data-baker.com/asynctts/synthesis/work"
    headers = {'content-type': 'application/json'}
    response = requests.post(url, data=data, headers=headers)
    code = json.loads(response.text).get("code")
    if code != 0:
        raise Exception(response.text)
    else:
        return json.loads(response.text).get("data")['workId']


# 查询合成结果
def get_audio(params):
    url = "https://openapi.data-baker.com/asynctts/synthesis/query"
    response = requests.get(url, params=params)
    code = json.loads(response.text).get("code")
    if code == 0:
        audio_url = json.loads(response.text).get("data")["audioUrl"]
        return audio_url
    else:
        return None

# 获取命令行输入参数
def get_args():
    text = '欢迎使用标贝开发平台。'
    parser = argparse.ArgumentParser(description='ASR')
    parser.add_argument('-client_secret', type=str, required=True)
    parser.add_argument('-client_id', type=str, required=True)
    parser.add_argument('--notify_url', type=str)
    parser.add_argument('--text', type=str, default=text)
    parser.add_argument('--voice_name', type=str, default='Jiaojiao')
    parser.add_argument('--audiotype', type=str, default='3')
    parser.add_argument('--sampleRate', type=str, default='16000')
    args = parser.parse_args()

    return args


def main(args):
    # 获取access_token
    client_secret = args.client_secret
    client_id = args.client_id
    access_token = get_access_token(client_secret, client_id)

    # 新建合成任务
    voice_name = args.voice_name
    text = args.text
    data = {'access_token': access_token, 'text': text, 'voiceName': voice_name, 'audiotype': 3, 'language': 'zh',
            'sampleRate': 16000}
    workId = send_text(json.dumps(data))
    print("send text successfully!", '  ', workId)

    # 查询合成结果
    query_params = {'client_id': client_id, 'access_token': access_token, 'work_id': workId}
    while True:
        audio_url = get_audio(query_params)
        if audio_url:
            break
        else:
            time.sleep(2)
            print('task is processing')

    audio_data = requests.get(audio_url)
    with open("test.mp3", "wb") as f:
        f.write(audio_data.content)
    print('task finished')


if __name__ == '__main__':
    try:
        args = get_args()
        main(args)
    except Exception as e:
        print(e)

命令行执行

python long_tts.py -client_secret=您的client_secret -client_id=您的client_id --text=欢迎使用标贝开放平台

PHP示例代码

<?php
//获取访问令牌
$client_secret = '***'; //应用secret
$client_id = '***'; //应用id
$grant_type = 'client_credentials'; //固定格式

//1.获取token
$url = 'https://openapi.data-baker.com/oauth/2.0/token?grant_type='.$grant_type.'&client_id='.$client_id.'&client_secret='.$client_secret;

//curl get请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //信任任何证书
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 检查证书中是否设置域名,0不验证
$token_res = curl_exec($ch);

//如果错误 查看错误信息
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);

//进行token信息解析
$token_info = json_decode($token_res,1);
$access_token = $token_info['access_token'];    //获取到的token信息
//var_dump($access_token);die;
//$access_token = '***';

//2.长文本语音合成
$url = 'https://openapi.data-baker.com/asynctts/synthesis/work';

$file_path = './test.txt';
$text = file_get_contents($file_path);
$notify_url = '***/tts_async';

$post_data['access_token'] = $access_token;
$post_data['text'] = $text;
$post_data['notifyUrl'] = $notify_url;
$post_data['voiceName'] = 'Jiaojiao';
$post_data =json_encode($post_data);

$Content_Type = 'application/json; charset=utf-8';
$headers = array(
    'Content-Type:'.$Content_Type
);
$ch = curl_init();
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 60); // 识别时长不超过原始音频
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
$res = curl_exec($ch);
if(curl_errno($ch))
{
    print curl_error($ch);
}
curl_close($ch);
//var_dump($res);die;
echo(json_decode($res,1)['message']);

C示例代码

代码地址:Github

JAVA示例代码

package com.databaker.web.tts;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;

/**
 * 长文本语音合成RESTFUL API接口调用示例
 * 附:长文本语音合成RESTFUL API文档 【https://www.data-baker.com/specs/file/tts_api_long_text】
 * 注意:仅作为demo示例,失败重试、token过期重新获取、日志打印等优化工作需要开发者自行完成
 *
 * @author data-baker
 */
public class TtsLongTextRestApiDemo {
    /**
     * 授权:需要在开放平台获取【https://ai.data-baker.com/】
     */
    private static final String clientId = "YOUR_CLIENT_ID";
    private static final String clientSecret = "YOUR_CLIENT_SECRET";

    /**
     * 获取token的地址信息
     */
    public static String tokenUrl = "https://openapi.data-baker.com/oauth/2.0/token?grant_type=client_credentials&client_secret=%s&client_id=%s";
    /**
     * 长文本合成API地址
     */
    public static String ttsLongTextUrl = "https://openapi.data-baker.com/asynctts/synthesis/work";

    /**
     * 轮询结果的API接口地址
     * 轮询操作非必须
     * 轮询频率不宜过高,一般5s或10s轮询一次即可
     *
     * @param args
     */
    public static String queryResultUrl = "https://openapi.data-baker.com/asynctts/synthesis/query";

    public static void main(String[] args) {
        String accessToken = getAccessToken();
        if (StringUtils.isNotEmpty(accessToken)) {
            doSynthesis(accessToken, "Nannan", "测试文本", 6, 5.0, 5.0, "https://openapi.data-baker.com/asynctts/synthesis/notify");
        }
    }

    /**
     * 实际合成逻辑
     * 1.如果选择通过回调的方式获取音频数据,开发者需开发一个回调接口,接口地址作为参数notifyUrl,用来接收合成的音频链接,具体写法可参考接口文档【https://www.data-baker.com/specs/file/tts_api_long_text】中的回调部分
     * 2.如果选择通过轮询的方式获取音频数据,可不提供回调地址notifyUrl,设置该参数为空字符串即可
     */
    public static String doSynthesis(String accessToken, String voiceName, String text, Integer audioType, Double speed, Double volume, String notifyUrl) {
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json");
        //构造requestBody
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("access_token", accessToken);
        jsonObject.put("voiceName", voiceName);
        jsonObject.put("text", text);
        jsonObject.put("volume", volume);
        jsonObject.put("speed", speed);
        jsonObject.put("audiotype", audioType);
        jsonObject.put("notifyUrl", notifyUrl);
        RequestBody body = RequestBody.create(mediaType, jsonObject.toJSONString());
        //构造request
        Request request = new Request.Builder()
                .url(ttsLongTextUrl)
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .build();
        try {
            Response response = client.newCall(request).execute();
            // 获取结果,并根据返回进一步进行处理。
            String result = response.body().string();
            response.close();
            System.out.println("result = " + result);
            JSONObject resultJson = JSON.parseObject(result);

            if (resultJson.containsKey("code") && resultJson.getIntValue("code") == 0) {
                // 如果请求正常,会返回作品id
                System.out.println("Request Success! task_id = " + resultJson.getJSONObject("data").getString("workId"));
                String workId = resultJson.getJSONObject("data").getString("workId");

                // 定时查询合成结果,如果已完成,获取音频数据
                // 该轮询操作非必须,如果设置了回调URL,服务端会在合成完成后主动推送音频数据,可跳过此操作。
                if (StringUtils.isNotEmpty(workId) && StringUtils.isEmpty(notifyUrl)) {
                    waitForSynthesisCompleting(queryResultUrl, clientId, accessToken, workId);
                }
            } else {
                //处理错误,主要的错误类别:Token失效、文本长度过长、使用了授权范围外的音色等
                System.out.println("Request Error: code=" + resultJson.getIntValue("code")
                        + ", message=" + resultJson.getString("message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 根据workID轮询作品在服务端的合成状态
     * 轮询操作非必须,如果设置了回调url,则服务端会在合成完成后主动回调
     */
    private static void waitForSynthesisCompleting(String url, String clientId, String token, String workId) {
        String fullUrl = url + "?workId=" + workId + "&client_id=" + clientId + "&access_token=" + token;
        System.out.println("query url = " + fullUrl);
        while (true) {
            Request request = new Request.Builder().url(fullUrl).get().build();
            try {
                OkHttpClient client = new OkHttpClient();
                Response response = client.newCall(request).execute();
                String result = response.body().string();
                response.close();
                System.out.println("waitForSynthesisCompleting result = " + result);
                JSONObject resultJson = JSON.parseObject(result);
                if (resultJson.containsKey("code")
                        && resultJson.getIntValue("code") == 0
                        && resultJson.containsKey("data")
                        && resultJson.getJSONObject("data").getString("audioUrl") != null) {
                    System.out.println("Tts Synthesis Finished! workId = " + resultJson.getJSONObject("data").getString("workId"));
                    System.out.println("Tts Synthesis Finished! audioUrl = " + resultJson.getJSONObject("data").getString("audioUrl"));
                    break;
                } else {
                    System.out.println("Tts synthesis still working...");
                }
                // 每隔10秒钟轮询一次状态。
                Thread.sleep(10000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static String getAccessToken() {
        String accessToken = "";
        OkHttpClient client = new OkHttpClient();
        //request 默认是get请求
        String url = String.format(tokenUrl, clientSecret, clientId);
        Request request = new Request.Builder().url(url).build();
        JSONObject jsonObject;
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                //解析
                String resultJson = response.body().string();
                jsonObject = JSON.parseObject(resultJson);
                accessToken = jsonObject.getString("access_token");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return accessToken;
    }
}

GO示例代码

package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"time"
)

type AuthInfo struct {
	AccessToken string `json:"access_token"`
	ExpiresIn   int    `json:"expires_in"`
	Scope       string `json:"scope"`
}
type ReqTtsParams struct {
	AccessToken string `json:"access_token"`
	Text        string `json:"text"`
	VoiceName   string `json:"voiceName"`
	NotifyUrl   string `json:"notifyUrl"`
	Speed       string `json:"speed,omitempty"`
	Volume      string `json:"volume,omitempty"`
	AudioType   int    `json:"audiotype"`
}

const grantType string = "client_credentials"

func GetToken(reqUrl, clientId, clientSecret string) (string, error) {
	// 超时时间:60秒
	client := &http.Client{Timeout: 60 * time.Second}
	urlParams := url.Values{}
	urlParams.Add("grant_type", grantType)
	urlParams.Add("client_id", clientId)
	urlParams.Add("client_secret", clientSecret)
	httpUrl := reqUrl
	httpUrl += "?"
	httpUrl += urlParams.Encode()
	fmt.Printf("httpUrl: %s\n\n", httpUrl)
	resp, err := client.Get(httpUrl)
	if err != nil {
		fmt.Printf("send http get token request failed, err: %s\n", err)
		return "", err
	}
	defer resp.Body.Close()
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("http get token request, readall body failed, err: %s\n", err)
		return "", err
	}
	authInfo := AuthInfo{}
	err = json.Unmarshal(result, &authInfo)
	if err != nil {
		fmt.Printf("auth info json.Unmarshal err: %s \n", err)
		return "", err
	}
	if len(authInfo.AccessToken) <= 0 {
		return "", errors.New("access token is null")
	}
	fmt.Printf("get token success. info: %#v \n", authInfo)
	return authInfo.AccessToken, nil
}

func SendTts(URL string, reqParam ReqTtsParams) (string, error) {
	// 超时时间:60秒
	client := &http.Client{Timeout: 60 * time.Second}
	reqUrl := URL
	fmt.Printf("reqUrl: %s\n\n", reqUrl)
	var resp *http.Response
	var err error
	jsonData, _ := json.Marshal(&reqParam)
	resp, err = client.Post(reqUrl, "application/json", bytes.NewReader(jsonData))
	if err != nil {
		fmt.Printf("send http tts request failed, err: %s \n", err)
		return "", err
	}
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		fmt.Printf("send http tts request return status code != 200\n")
		return "", errors.New("status code is not 200")
	}
	result, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("readall http body failed, err: %s \n", err)
		return "", err
	}
	return string(result), nil
}

func main() {
	var (
		clientId, clientSecret, text, voiceName, notifyUrl, speed, volume string
		audioType                                                         int
	)
	flag.StringVar(&clientId, "cid", "", "client id")
	flag.StringVar(&clientSecret, "cs", "", "client secret")
	flag.StringVar(&notifyUrl, "notify_url", "", "接收合成后的结果url")
	flag.StringVar(&text, "t", "标贝科技", "合成文本")
	flag.StringVar(&voiceName, "v", "jingjing", "发音人")
	flag.IntVar(&audioType, "audiotype", 6, "audiotype")
	flag.StringVar(&speed, "speed", "", "合成speed")
	flag.StringVar(&volume, "volume", "", "合成volume")
	flag.Parse()
	if len(os.Args) < 2 {
		flag.Usage()
		return
	}
	if len(clientId) <= 0 || len(clientSecret) <= 0 || len(text) <= 0 || len(voiceName) <= 0 || len(notifyUrl) <= 0 {
		fmt.Println("parameter error!!!")
		return
	}
	accessToken, err := GetToken("https://openapi.data-baker.com/oauth/2.0/token",
		clientId,
		clientSecret,
	)
	if err != nil {
		fmt.Println("get access token failed!!!! please check your client_id and client_secret.")
		return
	}
	param := ReqTtsParams{
		AccessToken: accessToken,
		Text:        text,
		VoiceName:   voiceName,
		AudioType:   audioType,
		NotifyUrl:   notifyUrl,
		Speed:       speed,
		Volume:      volume,
	}
	body, err := SendTts("https://openapi.data-baker.com/asynctts/synthesis/work", param)
	if err != nil {
		fmt.Printf("send tts http request failed. result: %s \n", body)
		return
	}
	fmt.Printf("send http request success. result: %s \n", body)
}

响应结果

  • 正确结果示例:workId可以唯一标志一次成功的调用,通过notifyUrl回调推送合成结果时,会同时返回这个序列号以及音频下载地址。
  • {
      "code": 0,
      "message": "成功",
      "data": {
        "workId": "L0191129150400644602680"
      }
    }
  • 错误结果示例
  • {
      "code": 30000,
      "message": "鉴权错误(access_token值不正确或已经失效)",
      "data": null
    }

回调说明

  • 长文本异步合成接口收到请求后,首先对请求参数进行初步校验,并马上返回。如果成功,返回的结果“code”是0,会同时返回此次合成对应的workId,然后进入异步合成和回调逻辑;如果校验失败,返回的错误码提示错误,丢弃当前合成文本放弃合成。
  • 长文本异步合成接口在回调时,请求的body中会包含workId和audioUrl字段。回调的请求方式示例如下
  • curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
       "audioUrl": "string",
       "workId": "3",
     }' 'https://openapi.data-baker.com/asynctts/synthesis/notify'
  • 建议处理方式:收到回调请求后,提取需要的信息,并在body中返回固定字符串
  • <xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>
  • 回调如果不成功,目前每隔5秒重试一次,总共重试4次(该策略可能会有变动)

回调示例代码

Python3示例

from flask import Flask, request
import json
import wget

app = Flask(__name__)


@app.route("/", methods=['GET', 'POST'])
def get_audio():
    url = json.loads(request.get_data())['audioUrl']
    wget.download(url)
    print("task finished successfully")

    return "finished"

将上述代码保存为server.py

命令行执行

export FLASK_APP=server
flask run -p 端口号 --host=服务器IP

Java示例

@ApiOperation(value = "测试用回调接口", notes = "该链接由参数notifyUrl设置,如果链接无法访问,将无法接收到回调的push信息。")
@PostMapping("/notify")
public void synthesisNotify(HttpServletRequest request, HttpServletResponse response) {
    String resXml = "";
    InputStream inStream;
    try {
        inStream = request.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len;
        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }
        // 获取asyncTts调用notifyUrl的返回信息
        String result = new String(outSteam.toByteArray(), "utf-8");
        log.info("dataBaker:长文本tts返回结果 ----result---- =" + result);
        // 关闭流
        outSteam.close();
        inStream.close();
        // String转换为json对象,然后业务处理
        JSONObject jsonObject = JSON.parseObject(result);
        String workId = jsonObject.getString("workId");
        String audioUrl = jsonObject.getString("audioUrl");
        //具体业务处理,例如转存音频等(可先返回结果,然后异步去完成业务逻辑)
        //todo
        //根据情况,向结果中赋值:正常情况下,选择下面的resSuccess;如果选择resFail,将会视为推送失败,标贝服务端将重新推送一次相同的内容
        //     * 返回成功xml
        //     */
        //    String resSuccess = "<xml$gt;<return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>";
        //    /**
        //     * 返回失败xml
        //     */
        //    String resFail = "<xml><return_code>FAIL</return_code><return_msg>报文为空</return_msg></xml>";resXml = Constant.resSuccess;
        //记录日志
        log.info("dataBaker:长文本tts回调返回作品  {}  的下载链接为:--->{}", workId, audioUrl);
        } catch (Exception e) {
            log.error("dataBaker:长文本tts回调异常:", e);
        } finally {
            try {
                // 处理业务完毕
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                log.error("dataBaker:长文本tts回调异常:out:", e);
            }
        }
    }

PHP示例

<?php
//官网在线合成长文本语音合成API SDK 回调接口
public function tts_async(){
    $audio_info = file_get_contents("php://input");
    $audio_arr = json_decode($audio_info,1);
    //对返回结果进行判断
    if(isset($audio_arr['audioUrl'])){
        //1.建议返回信息存储到日志文件 或者 本地文件,自行完成
        //2.对音频链接进行读取写入文件操作,自行完成(请求合成接口不设置audiotype参数,默认返回mp3格式)
        //3.对回调接口返回成功信息 return "<xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>";
    }
}

轮询获取结果说明

1.轮询接口采用GET请求方式,通过query参数传参,具体参数含义如下:

参数名称 参数格式 是否必填 说明
client_id String 授权对应的appKey或client_id
access_token String 通过client_id,client_secret调用授权服务获得见获取访问令牌
work_id String 作品id,用于获取对应作品的合成状态和结果数据

2.轮询的请求示例如下,建议10秒左右轮询一次:

curl -X GET 'https://openapi.data-baker.com/asynctts/synthesis/query?client_id=a4800cdd51184c29aeca390d78ff57f6&work_id=L0220512155058739224607&access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiKiJdLCJzY29wZSI6WyJ0dHMtbG9uZ3RleHQiXSwiZXhwIjoxNjUyNTA4NTEwLCJhdXRob3JpdGllcyI6WyIqIl0sImp0aSI6IjU2MDg2NjEyLTYyMzYtNDY1ZS04Njc4LWVhNWE1MGUxOGQwMSIsImNsaWVudF9pZCI6ImE0ODAwY2RkNTExODRjMjlhZWNhMzkwZDc4ZmY1N2Y2In0.8aYkauZ0mpOg5gPLj0D_q3efsMrCLVOW7pWnrUZAGSw'

3.轮询接口返回结果示例:

{
    "code": 0,
    "message": "成功",
    "data": {
        "audioUrl": "https://databaker-of-yuedu.oss-cn-huhehaote.aliyuncs.com/static_tts_file/c26c5dbf38b946dc8d187cfdf3b4f87e.wav?Expires=1652946664&OSSAccessKeyId=LTAI4Fktx2ckBLU3ZJizYTuW&Signature=6FXh%2FkCOPbuZqfTJEfNmtXGUFLU%3D",
        "workId": "L0220512155058739224607",
        "status": "已完成"
    }
}

错误码

错误码 含义
10001 access_token参数获取失败
10002 domain参数值错误
10003 language参数错误或不支持
10004 voice_name参数错误
10005 请对照音色表,检查sampleRare或audiotype参数是否正确
10009 text参数错误
10010 文本太长
20000 获取资源错误
20001 断句失败
20002 分段数错误
20003 分段后的文本长度错误
20004 获取引擎链接错误
20005 RPC链接失败错误
20006 引擎内部错误
20007 操作redis错误
20008 音频编码错误
30000 鉴权错误(access_token值不正确或已经失效)
30001 并发错误
30002 内部配置错误
30003 json串解析错误
30004 获取url失败
30005 获取客户IP地址失败
30006 任务队列错误
30007 用量不足
30008 授权已过期
40001 请求不是json结构
40002 缺少必须字段
40003 版本错误
40004 字段值类型错误
40005 参数错误
50001 处理超时
50002 内部rpc调用失败
50003 合成任务正在处理 ,请稍后再查
50004 合成失败,请检查参数或文本
50005 作品不存在,请确保clientId和workId填写正确