- ···
- 产品服务
- ···
- 解决方案
- ···
- 文档中心
- ···
# 一、接口说明
用户录音上传后,如果有空闲训练资源,最快20分钟之内模型训练结束;如果训练资源紧张,采用排队等待机制;训练发起方可采用轮询方式查询训练进度。
# 二、接口Demo
Java示例demo (opens new window)
python3示例demo (opens new window)
# 三、接口要求
接入声音克隆API时,需按照以下要求:
| 内容 | 说明 |
|---|---|
| 请求协议 | http[s](为提高安全性,强烈推荐https) |
| 请求域名 | http[s]: //ai-api.hivoice.cn/api/clone/ai-voice-clone-train |
| 接口鉴权 | 签名机制,详情请参照下方接口鉴权 |
| 字符编码 | UTF-8 |
| 响应格式 | 统一采用JSON格式 |
| 开发语言 | 任意 |
| 操作系统 | 任意 |
| 音频属性 | 采样率22k采样率,采样深度16bit、单声道 |
| 音频格式 | wav、pcm |
| 声音类型 | 男声、女声、童声 |
# 四、接口调用流程
如下参数需要在header中传递
| 参数名称 | 参数类型 | 是否必填 | 参数说明 |
|---|---|---|---|
| appKey | String | Y | 调用者应用的appKey |
| timestamp | String | Y | 时间戳字段(毫秒) |
| signature | String | Y | 签名,参考如下签名加密函数,签名字段:appKey、timestamp、appsercret(顺序不可变) |
# 1. 签名加密函数
# 1.1 加密流程
A)将appKey,timestamp,appsercret的参数值按照自然顺序拼接成字符串,注意:计算signature时所有参数不应进行URLEncode;
B)将A形成字符串获取SHA256摘要,形成一个64位的十六进制(字母大写)字符串,即为本次请求signature(签名)的值;
# 1.2 构造签名算法的JAVA代码示例
public static void main(String[] args) throws Exception {
String appKey = "45gn7md5n44******gv75saomys";
String timestamp = System.currentTimeMillis()+"";
String appSecret = "ba24a917a******b82a72e0d896";
List<String> paramsList =
Arrays.asList(
appKey,
timestamp,
appSecret
);
System.out.println(buildSignature(paramsList));
}
public static String buildSignature(List<String> paramsList) {
StringBuilder sb = new StringBuilder();
for (String param : paramsList) {
sb.append(param);
}
return getSHA256Digest(sb.toString());
}
private static String getSHA256Digest(String data) {
String digest = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] bytes = md.digest(data.getBytes("UTF-8"));
digest = byte2hex(bytes);
} catch (Exception e) {
logger.error("get bytes error ", e);
}
return digest;
}
private static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 2. 获取默认文本
请求uri:/voiceclone/v1/text
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Body参数:无
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object[] | 文本结果 |
| data.textId | String | 音频文本Id |
| data.readText | String | 音频文本 |
| data.readUrl | String | 样音url |
返回示例
{
"code": "0",
"data": [
{
"readText": "园子里,田野里,瞧去,一大片一大片满是的。"
"textId": "00000031",
"readUrl":"xxxxxx"
},
{
"readText": "坐着,躺着,打两个滚,踢几脚球,赛几趟跑,捉几回迷藏。",
"textId": "00000032",
"readUrl":"xxxxxx"
},
{
"readText": "风轻悄悄的,草绵软软的。",
"textId": "00000033",
"readUrl":"xxxxxx"
}
],
"msg": "success"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 3. 创建克隆任务
请求uri:/voiceclone/v1/task
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Body参数:
| 参数名称 | 参数类型 | 是否必须 | 备注 |
|---|---|---|---|
| user_id | String | Y | 接入方需保证用户ID唯一性 |
| name | String | Y | 克隆任务名称 |
| gender | Integer | Y | 性别,0:男 1:女 |
| age | Integer | Y | 年龄,0:成年(>=12) 1:儿童(<12,内测中) |
请求示例
{
"user_id": "abc",
"name": "name",
"gender": 0,
"age": 0
}
1
2
3
4
5
6
2
3
4
5
6
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 文本结果 |
| data.id | String | 克隆任务Id |
| data.user_id | String | 用户Id |
| data.name | String | 克隆任务名称 |
| data.gender | Integer | 性别 |
| data.age | Integer | 年龄 |
返回示例
{
"code": "0",
"data": {
"age": 0,
"gender": 0,
"id": "252",
"name": "name",
"user_id": "abc"
},
"msg": "success"
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 4. 音频提交检测
请求uri:/voiceclone/v1/task/{id}/audio/{textId}/upload
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | multipart/form-data | Y |
Path参数:
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| id | String | Y | 克隆任务id |
| textId | String | Y | 默认文本id |
Body参数(文件以表单形式上传):
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| file | 文件 | Y | 用户音频 |
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 音频检测结果 |
| data.valid | Integer | 音频是否可用,0:是,1:否 |
| data.matchPercent | Integer | 音频、文本匹配度 |
| data.highText | String | 标记为匹配失败的文本段 |
返回示例
{
"code": "0",
"msg": "success",
"data": {
"valid": 0,
"matchPercent": 97,
"highText": "只有中间的吧台,和角落上一个小小的表演圆台,被<mark>橙黄</mark>的牛眼灯照射着。"
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 5. 录制完成提交训练任务
请求uri:/voiceclone/v1/task/{id}/commit
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Path参数:
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| id | String | Y | 克隆任务编号 |
Body参数:无
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 空 |
返回示例:
{
"code": "0",
"msg": "success"
}
1
2
3
4
2
3
4
# 6. 我的声音列表接口
请求uri:/voiceclone/v1/user/{user_id}/voices
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Path参数:
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| user_id | String | Y | 用户唯一标识 |
Body参数:无
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object[] | 克隆声音列表 |
| data.age | Integer | 年龄 |
| data.gender | Integer | 性别 |
| data.id | String | 克隆任务Id |
| data.name | String | 克隆任务名称 |
| data.voiceId | String | 音色Id,用于合成音频的数据 |
| data.trainState | Integer | 训练状态,0:无效训练 1:训练成功 2:训练中 3:训练失败 4:已过期 5:已删除 |
| data.errorCode | String | 训练失败的唯一码 |
| data.errorMsg | String | 训练失败的描述信息 |
返回示例:
{
"code": "0",
"msg": "success",
"data": [
{
"age": 0,
"createTime": "2022-11-23 18:21:00",
"gender": 0,
"id": "abc",
"name": "bbk",
"trainState": 1,
"voiceId": "5491685dbf244b1cbd2ce99a045c467b",
"errorCode":"20481",
"errorMsg":""
}
]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 7. 删除声音
请求uri:/voiceclone/v1/voice/delete/{id}
请求方式:post
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Path参数:
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| id | String | Y | 克隆任务编号 |
Body参数:无
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 空 |
返回示例
{
"code": "0",
"msg": "success"
}
1
2
3
4
2
3
4
# 8. 查询训练状态
此接口需要调用方轮训请求
请求uri:/voiceclone/v1/task/status/{id}
请求方式:post
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | application/json | Y |
Path参数:
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| id | String | Y | 克隆任务编号 |
Body参数:无
响应结果
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 克隆声音列表 |
| data.trainState | Integer | 训练状态,0:无效训练 1:训练成功 2:训练中 3:训练失败 4:已过期 5:已删除 |
| data.modelAddress | String | 离线模型下载地址,仅限离线合成场景使用 |
| data.errorCode | String | 训练失败的唯一码 |
| data.errorMsg | String | 训练失败的描述信息 |
返回示例
{
"code": "0",
"msg": "success",
"data": {
"trainState": 1,
"modelAddress": "https://xxxxxx",
"errorCode":"20481",
"errorMsg":""
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 9. 环境噪音检测
请求uri:/voiceclone/v1/task/checkenv
请求方式:POST
Headers:
| 参数名称 | 参数值 | 是否必填 | 备注 |
|---|---|---|---|
| Content-Type | multipart/form-data | Y |
Body参数(文件以表单形式上传):
| 参数名称 | 参数类型 | 是否必填 | 备注 |
|---|---|---|---|
| file | 文件 | Y | 环境检测音频 |
返回参数:
| 参数名称 | 参数类型 | 备注 |
|---|---|---|
| code | String | 返回码,0表示成功,其他表示异常,见错误码 |
| msg | String | 错误描述 |
| data | Object | 音频检测结果 |
| data.envDecibel | Integer | 环境噪音分贝值 |
| data.valid | Integer | 样音检测编码,0:声音检测成功,1:环境检测不通过(声音大于20分贝) |
返回示例
{
"code": "0",
"msg": "success",
"data": {
"envDecibel": 20,
"valid": 1
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 五、错误码
| 错误码 | 说明 | 解决办法 |
|---|---|---|
| 0 | 成功 | |
| 20401 | appkey不存在 | 检查appkey是否配置正确 |
| 20402 | 请求参数错误 | 客户端检查参数是否正确 |
| 20403 | 文件为空 | 检查音频文件是否存在 |
| 20404 | 训练任务提交失败 | 检查任务编号是否正确 |
| 20405 | 可供训练的录音文件不足 | 音频文件不能少于20 |
| 20406 | 套餐已用完 | 购买时长套餐 |
| 20407 | 环境噪音检测不通过 | 找个安静地方录制音频 |
| 20408 | 训练中的任务不允许删除 | 训练完成后可删除 |
| 20499 | 服务器内部错误 | 建议重试,或者提工单,工单详情请提供任务编号 |