声纹识别
一、接口描述
1. 功能描述
声纹识别基于说话人的声音提供说话人确认功能。
2. 能力说明
声纹识别API提供说话人注册以及说话人确认的功能。用户可以先用声音进行注册,再根据声音进行说话人确认。
3. 音频要求
- 目前支持的音频格式为:wav、mp3、amr
- 音频采样率为:16 KHz
- 音频通道数:单通道
- 一次请求的音频最大时长:60 秒
4. 接口使用
平台为每个 API 提供试用体验服务,您在 AI 市场选择“免费试用”规格下单后,即可开始体验业内领先的人工智能 API 服务。 免费试用服务具有调用量、QPS 限制,如需更高性能的 API 服务,可以提交咨询工单,联系京东 AI 扩容购买。
在获得使用权限后,您可使用已经封装好的 SDK 参照 接口鉴权 规则进行相应开发,整体流程详见 接入流程 。
二、请求说明
1. 接口地址
https://aiapi.jd.com/jdai/vpr
2. 请求方式
post
3. 请求参数
(1)query 请求参数
公共请求参数
名称 | 类型 | 必填 | 示例值 | 描述 |
---|---|---|---|---|
appkey | string | 是 | 80d2b762ecb86593f9668526920f46c | 您的 appkey,可在买家中心控制台中获取 |
timestamp | long | 是 | 1541491668060 | 请求的时间戳,精确到毫秒,timestamp 有效期 5 分钟 |
sign | string | 是 | 2e148773a0337a8f2200ba90d445f083 | 签名,根据规则MD5(secretkey + timestamp) |
(2)header 请求参数
业务请求参数
名称 | 类型 | 必填 | 示例值 | 描述 |
---|---|---|---|---|
Content-Type | string | 是 | application/octet-stream | 内容类型:
不可用的Content-Type: - multipart/form-data - application/x-www-form-urlencoded |
Application-Id | string | 否 | your Application-Id | 产品 ID:
- 业务方应用名称,由业务方在客户端自行生成 |
Request-Id | string | 是 | *56a847e6-84c0-4c01-bf4b-d566f2d2dd11 | 请求ID:
- *注意:示例值仅供参考,正式使用请务必通过 uuid 生成 - 对于同一次请求 Request-Id 需要保持一致,多次请求使用同一个将会产生不可预知的错误 |
User-Id | string | 是 | IMEI-12345678 | 用户ID:
- *注意:示例值仅供参考 - 用户id是某一个人唯一的身份id |
Sequence-Id | int | 是 | -1 | 语音传输分段号:
- 从 1 开始依次递增,最后一段语音取负值,分为下述两种情况: 1. 在一个 Request-Id 中,上传整个音频文件(整包请求)时:填 -1 2. 在一个 Request-Id 中,音频文件分段上传(流式分包请求)时,遵循默认规则依次递增。例如:一次语音识别请求中,音频分 10 次上传,则 Sequence-Id 依次为:1,2,3,4,5,6,7,8,9,-10 |
Server-Protocol | int | 是 | 1 | 通信协议版本号:
- 默认填 1 |
Net-State | int | 是 | 2 | 客户端网络状态:
- NETSTATE_NO_NETWORK = 0; - NETSTATE_NO_WIFI_MOBILE = 1; - NETSTATE_WIFI = 2; - NETSTATE_CDMA = 3; - NETSTATE_EDGE = 4; //移动 2.5G - NETSTATE_EVDO_0 =5; - NETSTATE_EVDO_A = 6; - NETSTATE_GPRS = 7; - NETSTATE_HSDPA = 8; //联通 3G - NETSTATE_HSPA = 9; - NETSTATE_HSUPA = 10; - NETSTATE_UMTS = 11; - NETSTATE_EHRPD = 12; - NETSTATE_EVDO_B = 13; - NETSTATE_HSPAP = 14; - NETSTATE_IDEN = 15; - NETSTATE_LTE = 16; - NETSTATE_UNKOWN_MOBILE = 20; |
Applicator | int | 是 | 1 | 业务方信息:
- 0:内部业务方 - 1:外部业务方 |
Property | JSON | 否 | {...} | 语音识别请求参数:
- 注意:如果 Sequence-Id 为 1 或 -1 时,则 Property 参数必须要填;其他情况下,该参数可选填 |
- Property 字段
名称 | 类型 | 必填 | 示例值 | 描述 |
---|---|---|---|---|
autoend | bool | 是 | false | 服务端自动断尾检测(VAD)功能开关:
- false:不开启 VAD 功能 - true:开启 VAD 功能 |
platform | string | 是 | Linux&Centos&7.3 | 平台信息:
格式:{系统信息}&{设备信息}&{系统版本号} - 系统信息:如 Android,iOS,Linux,Windows - 设备信息:如 Pixel 3,iPhone X 等 - 系统版本号:设备系统版本,如 2.3.3,4.2.1 等 - 示例:Android&Pixel 3&7.1;iOS&iPhone X&11.4.1 |
version | string | 是 | 0.0.0.1 | 客户端版本信息 |
vpr_mode | string | 是 | enroll | 表示本次请求是注册还是说话人确认,取值为enroll, test。注册时设为enroll, 说话人确认时设为test。
-注:需要先注册两遍声纹,才能进行说话人确认。 |
encode | JSON | 是 | {...} | 音频参数 |
- encode 字段
名称 | 类型 | 必填 | 示例值 | 描述 |
---|---|---|---|---|
channel | int | 是 | 1 | 音频声道数:
- 目前只支持单声道,填 1 |
format | string | 是 | wav | 音频声道数:
- 目前支持 wav,amr,mp3 格式 |
sample_rate | int | 是 | 16000 | 音频采样率:
- 目前只支持16KHz,填 16000 |
(3)body 请求参数
填充待识别的音频数据(二进制)。 音频数据可按照自定义长度进行切分,按顺序分包上传,并与 header 请求参数中的 Sequence-Id 参数的顺序保持对应。
4. 请求代码示例
Python 3 示例程序如下:
import requests
import json
import time
import uuid
import hashlib
from urllib.parse import urlencode
import sys
import importlib
importlib.reload(sys)
url = 'https://aiapi.jd.com/jdai/vpr'
encode = {
'channel':1,
'format':'wav',
'sample_rate':16000
}
Property = {
'platform':'Linux&Centos&7.3',
'version':'0.0.0.1',
'vpr_mode':'enroll',
'autoend':False,
'encode':encode,
}
headers = {
'Content-Type':'application/octet-stream',
'Application-Id':'123456789',
'Request-Id':str(uuid.uuid1()),
'User-Id':'jdai-vpr-demo', # your user-id
'Sequence-Id':str(-1),
'Server-Protocol':str(1),
'Net-State':str(2),
'Applicator':str(1),
'Property':json.dumps(Property)
}
query = {
'appkey':'your appkey', #need change to your appkey
'timestamp':'',
'sign':''
}
audiofile = '16k_audio.wav' #change to your audio file
secretkey = 'your secretkey' #need change to your secretkey
def test_single(audiofile):
query['timestamp'],query['sign'] = sign(secretkey)
url_query = '?'.join([url, urlencode(query)])
#seq = 1
#packagelen = 4000
with open(audiofile, mode='rb') as f:
while True:
audiodata=f.read()
#audiodata=f.read(int(packagelen))
if not audiodata:
break
#else:
#if len(audiodata) < int(packagelen):
#headers['Sequence-Id'] = str(-seq)
#else:
#headers['Sequence-Id'] = str(seq)
r = requests.post(url_query, headers=headers, data=audiodata)
#seq += 1
print(r.text)
def sign(secretkey):
m = hashlib.md5()
nowTime = int(time.time() * 1000)
before = secretkey + str(nowTime)
m.update(before.encode('utf8'))
return str(nowTime), m.hexdigest()
if __name__ == '__main__':
audiofile = sys.argv[1] if len(sys.argv) > 1 else audiofile
test_single(audiofile)
参数说明
发送第一包数据必须上传 Property 字段:
Host: aiapi.jd.com
Accept: */*
Application-Id:123456789
Request-Id:56a847e6-84c0-4c01-bf4b-d566f2d2dd11
User-Id:IMEI-123456789
Sequence-Id:1
Server-Protocol:1
Net-State:2
Applicator:1
Property:{"autoend":false,"encode":{"channel":1,"format":"wav","sample_rate":16000},"platform":"Linux&Centos&7.3","version":"0.0.0.1","vpr_mode":"enroll"}
Content-Length: 3200
Content-Type: application/octet-stream
Expect: 100-continue
发送其他数据包或最后一包,可以不需要上传 Property 字段,音频切分的最后一包 Sequence-Id 取负值:
Host: aiapi.jd.com
Accept: */*
Application-Id:123456789
Request-Id:56a847e6-84c0-4c01-bf4b-d566f2d2dd11
User-Id:IMEI-123456789
Sequence-Id:-2
Server-Protocol:1
Net-State:2
Applicator:1
Content-Length: 3200
Content-Type: application/octet-stream
Expect: 100-continue
三、返回说明
1. 返回参数
(1)公共返回参数
名称 | 类型 | 示例值 | 描述 |
---|---|---|---|
code | string | 1000 | 参见下方错误码-系统级错误码 |
charge | boolean | false 或 true | false:不扣费, true:扣费 |
remainTimes | long | 1305 | 剩余调用次数;免费api:每天剩余调用次数;收费api:剩余次数;无限制时为-1 |
remainSeconds | long | 1223456 | 剩余调用时间(s);免费api:-1;收费api:剩余调用时间;无限制时为-1 |
msg | string | 查询成功 | 参见下方错误码-系统级错误码 |
result | object | {...} | 查询结果 |
(2)业务返回参数
服务器返回的识别结果采用 JSON 格式:
名称 | 类型 | 示例值 | 描述 |
---|---|---|---|
request_id | string | 56a847e6-84c0-4c01-bf4b-d566f2d2dd11 | 请求ID |
status | int | 0 | 状态码 |
index | int | -1 | 返回结果编号,负数表示全部最终结果 |
message | string | 语音数据为空 | 错误信息(返回正常时该字段的值为空) |
result | JSON | {...} | 识别结果,其中包含text对象,其值可取以下几个值:
not_enrolled(尚未注册),
enrolling(注册中), enrlled(注册完成), reject(验证失败), accept(验证通过) |
2. 返回示例
{
"code": "10000",
"charge": false,
"remainTimes": 4998,
"remainSeconds": -1,
"msg": "查询成功",
"result": {
"request_id": "56a847e6-84c0-4c01-bf4b-d566f2d2dd11",
"status": 0,
"index": -1,
"message": "",
"result": [
{
"text": "accept"
}
]
}
}
四、错误码
1. 系统级错误码
2. 业务错误码
业务错误码(status) | message | 说明 |
---|---|---|
61001 | speech data is empty. | 语音数据为空 |
61002 | speech data is too long. | 语音数据过长,一次请求音频不能超过一分钟 |
61003 | request params error. | 请求参数出错,缺少 Request-Id、Sequence-Id 或 Application-Id 等。 |
61004 | speech data file header error. | 音频头部格式解析错误 |
61005 | speech sample rate or channel error. | 音频采样率或通道数错误 |
61006 | speech format error. | 音频格式错误 |
62001 | codec error. | 服务内部音频解码错误 |
62002 | am server internal error. | 服务内部am-server模块错误 |
62003 | connect to decoder server error. | 服务内部链接engine-server模块错误 |
63001 | vpr userid too long. | 注册用户名过长 |
63002 | vpr mode error. | 不支持的声纹模式 |
63003 | vpr audio too short. | 音频文件过短 |
63004 | vpr not enrolled. | 该用户尚未注册声纹 |
63005 | vpr other error. | 服务内部其他错误 |
63007 | vpr other request enrolling or testing this userid. | 该用户id正在被其他请求进行声纹注册或声纹认证 |
63009 | vpr reqid is invalidation. | 该请求已失效 |