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接收到用户上传的音频列表(须由同一人录制且满足总有效时长要求)后,先对音频数据进行预校验,通过后即返回与训练相关的modelId。预校验成功后自动开启与modelId关联的训练任务。需要注意的是,用户调用该接口上传音频的同时需要额外提供一个回调url,当模型训练完成后,通过事先提供的回调url通知模型训练结果(成功或失败)。 训练结束且成功后用户就可使用modelId直接调用语音合成接口合成音频。

参数设置

  • 支持音频文件的编码格式及文件名的后缀: wav,pcm
  • 支持音频文件的采样率: 16000Hz
  • 支持音频文件的位深:16bits
  • 支持的语言:中文
  • 音频有效时长:不小于3分钟
  • 音频的音质、音量均对模型效果有直接影响,请保证音频的录音环境相对安静、音频人声音量不能太小。

使用方法

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

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

3. 调用定制模型接口,具体参数详见请求说明

4. 接收模型ID,具体参数详见响应结果

服务地址

访问类型 说明 URL Host
外网访问 提交复刻任务接口,只支持POST调用 https://openapi.data-baker.com/gramophone/v1/submit openapi.data-baker.com

交互流程

请求说明

参数名称 参数格式 是否必填 说明
access_token String 通过client_id,client_secret调用授权服务获得见获取访问令牌
originFiles MultipartFile[] 音频列表,需满足一定条件:
1.格式为pcm或wav
2. 采样率为16000hz,位深为16bit,单声道
3. 有效时长最好不小于3分钟(接口实际是以识别出的字数作为判定标准)
mobile String 手机号,用于接收短信提醒
notifyUrl String 该地址用于接收合成结果,该地址必须为外网可访问的url,不能携带参数。

请求示例

curl -L -X POST 'https://openapi.data-baker.com/gramophone/v1/submit' \
-F 'access_token=64c16f14-ac37-4dd8-9d56-a82e32b2d8d1' \
-F 'notifyUrl=https://openapi.data-baker.com/gramophone/v1/api/notify' \
-F 'originFiles=@/C:/Users/xxx/Desktop/0baf0cb3fdc14a049c9f615c69c1c50b/origin/1597222394369.wav' \
-F 'originFiles=@/C:/Users/xxx/Desktop/0baf0cb3fdc14a049c9f615c69c1c50b/origin/1597222451867.wav' \
-F 'originFiles=@/C:/Users/xxx/Desktop/0baf0cb3fdc14a049c9f615c69c1c50b/origin/1597222475643.wav' \
-F 'originFiles=@/C:/Users/xxx/Desktop/0baf0cb3fdc14a049c9f615c69c1c50b/origin/1597222497181.wav' \

Python示例代码

代码地址:Github

Python3示例如下:

import requests
import json
import argparse


# 获取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 create_model(data, files):
    url = "https://openapi.data-baker.com/gramophone/v1/submit"
    response = requests.post(url, data=data, files=files)
    code = json.loads(response.text).get("code")
    if code != "20000":
        raise Exception(response.text)
    else:
        model = json.loads(response.text).get("data")["modelId"]
        print(model)


# 获取命令行输入参数
def get_args():
    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('-file_path', type=str, required=True)
    parser.add_argument('-notifyUrl', type=str, required=True)
    parser.add_argument('--mobile', type=str)

    args = parser.parse_args()

    return args


if __name__ == '__main__':
    try:
        args = get_args()

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

        files = [
            ('originFiles', (
            '101.wav', open('101.wav', 'rb'),
            'audio/wav')),
            ('originFiles', (
            '201.wav', open('201.wav', 'rb'),
            'audio/wav')),
            ('originFiles', (
            '301.wav', open('301.wav', 'rb'),
            'audio/wav')),
            ('originFiles', (
            '401.wav', open('401.wav', 'rb'),
            'audio/wav'))
        ]
        # 读取参数
        notifyUrl = args.notifyUrl
        mobile = args.mobile
        data = {'access_token': access_token, 'notifyUrl': notifyUrl, 'mobile': mobile}
        create_model(data, files)
        print("task finished successfully")
    except Exception as e:
        print(e)

命令行执行

python audio_file_recognition.py -client_secret=您的client_secret -client_id=您的client_id -notifyUrl=您的回调地址

JAVA示例代码

package com.databaker.web.tts;

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

import java.io.File;
import java.util.ArrayList;
import java.util.List;


/**
 * 声音复刻RESTFUL API接口调用示例
 * 附:声音复刻RESTFUL API文档 【https://www.data-baker.com/specs/file/reprint_api_restful】
 *
 * 注意:仅作为demo示例,失败重试、token过期重新获取、日志打印等优化工作需要开发者自行完成
 *
 * @author data-baker
 */
public class TtsSoundReproductionApiDemo {

    /**
     * 授权:需要在开放平台获取【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 soundReproductionUrl = "https://openapi.data-baker.com/gramophone/v1/submit";

    /**
     * 音频列表,需满足一定条件:
     * 1.格式为pcm或wav
     * 2.采样率为16000hz,位深为16bit,单声道
     * 3.有效时长最好不小于3分钟(接口实际是以识别出的字数作为判定标准)
     */
    public static List<File> originFiles = new ArrayList<>();

    public static void main(String[] args) {
        String accessToken = getAccessToken();
        if (StringUtils.isNotEmpty(accessToken)) {
            doSoundReproduction(accessToken, originFiles, "mobile", "https://openapi.data-baker.com/gramophone/v1/api/notify");
        }
    }

    /**
     * 提交复刻任务
     *
     * 开发者需开发一个回调接口,接口地址作为参数notifyUrl,用来接收模型训练的结果,具体写法可参考接口文档【https://www.data-baker.com/specs/file/reprint_api_restful】中的回调部分
     */
    private static void doSoundReproduction(String accessToken, List<File> originFiles, String mobile, String notifyUrl) {
        //创建连接
        OkHttpClient client = new OkHttpClient();
        //构建requestBody,传入参数
        MultipartBody.Builder requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM);
        for (File file : originFiles) {
            RequestBody body = RequestBody.create(file, MediaType.parse("multipart/form-data"));
            String filename = file.getName();
            requestBody.addFormDataPart("originFiles", filename, body);
        }
        requestBody.addFormDataPart("access_token", accessToken);
        requestBody.addFormDataPart("mobile", mobile);
        requestBody.addFormDataPart("notifyUrl", notifyUrl);

        //构造request
        Request request = new Request.Builder()
                .url(soundReproductionUrl)
                .method("POST", requestBody.build())
                .build();
        try {
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                System.out.println("调用成功,返回结果:" + response.body().string());
            } else {
                System.out.println("调用失败,返回结果:" + response.body().string());
            }
        } 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;
    }
}

响应结果

正确结果示例:modelId可以唯一标志一个模型,通过notifyUrl回调推送合成结果时,会同时返回这个modelId和训练的结果及原因。如果训练成功,可以使用该modelId作为voice_name进一步进行tts功能的调用(参考: https://www.data-baker.com/specs/file/tts_api_restful)。

{
  "code": 20000,
  "message": "成功",
  "data": {
    "modelId": "714bef4b24****************8e68ballpx3"
  }
}

错误结果示例

{
  "code": 30000,
  "message": "鉴权错误(access_token值不正确或已经失效)",
  "data": null
}

回调说明

  • 声音复刻接口收到请求后,首先对请求参数进行初步校验,并马上返回。如果成功,返回的结果“code”是0,会同时返回此次模型对应的modelId,然后进入异步训练和回调逻辑;如果校验失败,返回的错误码提示错误,丢弃当前音频数据放弃训练。
  • 请求的body中会包含modelId、modelStatus和reason字段。modelStatus = “success”表示成功,modelStatus = “fail”表示失败,reason说明具体原因。回调的请求方式示例如下

    curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
      "modelStatus": "fail",
      "modelId": "714bef4b24****************8e68ballpx3",
      "reason":"音频有效时长不足(识别出的字数不足500字)"
    }' 'https://openapi.data-baker.com/gramophone/v1/api/notify'
  • 建议处理方式:收到回调请求后,提取需要的信息,并在body中返回固定字符串

    <xml><return_code>SUCCESS</return_code><return_msg>OK</return_msg></xml>
  • 回调如果不成功,目前每隔5秒重试一次,重试4次(该策略可能会有变动)

Python回调示例代码

from flask import Flask, request
import json

app = Flask(__name__)


@app.route("/", methods=['GET', 'POST'])
def get_audio():
    data = str(json.loads(request.get_data()))
    with open('clong.log', 'w') as f:
        f.write(data)

    return "finished"

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);
        }
        // 获取声音复刻api调用notifyUrl的返回信息
        String result = new String(outSteam.toByteArray(), "utf-8");
        log.info("dataBaker:声音复刻api返回结果 ----result---- =" + result);
        // 关闭流
        outSteam.close();
        inStream.close();
        // String转换为json对象,然后业务处理
        JSONObject jsonObject = JSON.parseObject(result);
        //该参数表示模型id
        String modelId = jsonObject == null ? "" : jsonObject.getString("modelId");
        //该参数表示模型当前状态:可能的值为success/fail, 其中,success=训练成功 fail=训练失败
        String modelStatus = jsonObject == null ? "" : jsonObject.getString("modelStatus");
        //该参数表示原因(文案可能会有变动),成功时为空字符串,失败时为失败原因说明
        String reason = jsonObject == null ? "" : jsonObject.getString("reason");
        //具体业务处理,例如尝试tts调用等(可先返回结果,然后异步去完成业务逻辑)
        //todo
        //根据情况,向结果中赋值:正常情况下,选择下面的resSuccess;如果选择resFail,将会视为推送失败,标贝服务端将重新推送一次相同的内容
        //     * 返回成功xml
        //     */
        //    String resSuccess = "<xml><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:声音复刻api回调返回模型  {}  的状态为:--->{}", modelId , modelStatus);
        } catch (Exception e) {
            log.error("dataBaker:声音复刻api回调异常:", e);
        } finally {
            try {
                // 处理业务完毕
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                log.error("dataBaker:声音复刻api回调异常:out:", e);
            }
        }
    }

错误码

错误码 含义
20000 请求成功
30000 鉴权错误(access_token值不正确或已经失效) 授权相关错误(鉴权未通过、qps超限、授权到期等)
30008 授权禁用
30009 授权到期
30010 调用次数超过限制
30013 授权不支持声音复刻
40000 参数获取失败或未传输 客户端参数错误
40002 提交次数已达到最大限制
40003 接口请在有效期内使用
40006 文件大小或音频时长不符合要求
50000 系统内部错误 服务端错误信息
50001 操作redis错误
50002 引擎下载失败