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
常见问题 常见问题
开发者文档下拉
语音合成
语音识别

声纹识别

功能介绍

通过声音识别说话人身份,仅需采集三段说话人音频注册到声纹库,即可通过1:1、1:N产品实现声纹识别。

音频要求

  • 音频时长:最佳 10 秒,最小 1 秒,最大 30 秒
  • 支持音频格式:pcm
  • 音频采样率:16000Hz
  • 位深:16bit
  • 声道:单声道

使用方法

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

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

3. 获取token后,发送创建声纹库请求:按照请求说明发送请求,具体参数详见 创建声纹id

4. 获取声纹库注册id后,发送声纹注册请求,按照请求说明发送请求,具体参数详见 声纹注册

5. 注册声纹三次成功后,依据需求进行1:1或1:N验证,发送1:1或1:N验证,具体参数详见1:1请求说明1:N请求说明

创建声纹特征id

功能介绍:对声纹数据进行存储和管理,调用接口返回可用的声纹特征id

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/createid

请求参数

调用接口返回可用的声纹特征id

请求参数采用 json 方式,Content-Type 为 application/json

params字段说明

参数名称 类型 是否必填项 说明
access_token string yes 通过 client_id,client_secret 调用授权服务获得见 获取访问令牌

请求示例

curl -X POST -H"Content-Type:application/json"
https://openapi.data-baker.com/vpr/createid
-d '{"access_token" : "eyJhb......"}'

响应结果

Content-Type 为 application/json

返回数据为 json 格式,err_msg 字段为 SUCCESS 表示调用成功

参数名称 类型 说明
err_msg String 错误信息
err_no Int 错误码
log_id String 日志标识
registerid String 声纹特征 id

返回示例

     {
	"err_msg": "SUCCESS",
	"log_id": "1637151763693260",
	"err_no": 90000,
	"registerid": "1760157933973465631"
     }
      

声纹注册

功能介绍: 保存基础对比音频,最少需要调用 3 次该接口完成注册过程,当某次注册返回失败时,需要重新提交注册,直到注册完成

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/register

最少需要调用 3 次该接口完成注册过程,当某次注册返回失败时,需要重新提交注册,直到注册完成

请求参数

请求参数采用 json 方式,Content-Type 为 application/json

params字段说明

参数名称 类 型 是否必填 说明
access_token String 通过client_id,client_secret调用授权服务获得见获取访问令牌
format String pcm
audio String 音频数据 base64(单声道,采样率16K,位深16 位,pcm音频,最短1秒,最长30秒)
registerId String 调用创建声纹id接口获取
name String 自定义名字
scoreThreshold Float 注册有效分数,不得低于系统默认值15.0,推荐值30.0
vad Int 是否打开vad(语音端点检测)处理,默认为关闭
打开vad功能可以提升声纹识 别准确度,但会增加响应时间
1:打开
0:关闭

请求示例

curl -X   POST -H"Content-Type:application/json"
https://openapi.data-baker.com/vpr/register
-d '{ "access_token": "eyJ...", "format":"wav", "audio":"AAA", "registerId":"5ae...","name":"testa", "scoreThreshold":65.0 } '

响应结果

Content-Type 为 application/json

返回数据为 json 格式,err_msg 字段为 错误信息

参数名称 类型 说明
err_msg String 错误信息
err_no Int 错误码
log_id String 日志标识
suc_num Int 注册成功次数,为 3 时表示完成注册

返回示例

      {
	"err_msg": "SUCCESS",
	"log_id": "1637152591998223",
	"err_no": 90000,
	"suc_num": 1
      }
      

声纹验证(1:1)

功能介绍: 上传音频与已其中一个声纹库中的音频特征比对,返回是否匹配

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/match

上传音频与已存在特征比对,返回是否匹配

请求参数

请求参数采用 json 方式,Content-Type 为 application/json

params 字段说明

参数名称 类型 是否必填项 说明
access_token String 通过 client_id,client_secret 调用授权服务获得见 获取访问令牌
format String pcm
audio String 音频数据 base64(单声道,采样率16K,位深16 位,pcm音频,最短1秒,最长30秒)
matchId String 待匹配声纹id
scoreThreshold Float 比对分数设置,得分高于该数值则比对成功,不得低于系统默认值5.0,推荐值15.0
vad Int 是否打开vad(语音端点检测)处理,默认为关闭
打开vad功能可以提升声纹识 别准确度,但会增加响应时间
1:打开
0:关闭

请求示例

curl -X POST -H"Content-Type:application/json"
https://openapi.data-baker.com/vpr/match
-d  '{ "access_token": "eyJ...  ", "format":"pcm", "audio":"AAAAAA", "scoreThreshold":60.0, "matchId":"be0..." }'

响应结果

Content-Type 为 application/json

返回数据为 json 格式,err_msg 字段为 错误信息

参数名称 类型 说明
err_msg String 错误信息
err_no Int 错误码
log_id String 日志标识
matchStatus Int 1 表示比对成功,0 表示比对失败
score String 比对分数
{
    "matchStatus": 0,
    "err_msg": "SUCCESS",
    "log_id": "1639473151396592",
    "err_no": 90000,
    "score": 1.5
}

查询声纹状态码

功能介绍: 查询声纹注册是否成功

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/status

请求参数

请求参数采用 json 方式,Content-Type 为 application/json

params 字段说明

参数名称 类型 是否必填 说明
access_token String yes 通过 client_id,client_secret 调用授权服务获得见 获取访问令牌
registerId String yes 调用创建声纹id接口获取

请求示例

curl -X POST -H"Content-Type:application/json"
https://openapi.data-baker.com/vpr/status
-d '{"access_token" : "eyJ... ","registerId":"53a..."}'

响应结果

content_type 为 application/json

返回数据为 json 格式,err_msg 字段为 错误信息

参数名称 类型 说明
err_msg String 错误信息
err_no Int 日志标识
log_id String 错误码
status Int 声纹注册次数,3:注册成功,0:未注册

返回示例

   {
    "err_msg": "SUCCESS",
    "log_id": "1637152702700241",
    "err_no": 90000,
    "status": 3
    }
        

删除声纹

功能介绍: 删除已注册的声纹

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/delete

请求参数

请求参数采用 json 方式,Content-Type 为 application/json

params 字段说明

参数名称 类型 是否必填 说明
access_token String yes 通过 client_id,client_secret 调用授权服务获得见 获取访问令牌
registerId String yes 待匹配声纹id

请求示例

curl -X POST -H"Content-Type:application/json"
 https://openapi.data-baker.com/vpr/delete
-d '{"access_token" : "eyJ... ","registerId":"53a..."}'

响应结果

content_type 为 application/json

返回数据为 json 格式,err_msg 字段为 错误信息

参数名称 类型 说明
err_msg String 错误信息
err_no Int 错误码
log_id String 日志标识
status Int 删除声纹的注册状态,3:注册成功,0:未注册

响应示例

{
    "err_msg": "SUCCESS",
    "log_id": "1639473151396592",
    "err_no": 90000,
    "status": 1
}

声纹对比(1:N)

功能介绍: 上传音频,比对库中所有音频特征,返回匹配列表

接口类型: REST API

服务接口

https://openapi.data-baker.com/vpr/search

用户上传音频,比对库中所有特征,返回匹配的特征列表

请求参数

请求参数采用 json 方式,Content-Type 为 application/json

params 字段说明

参数名称 类型 是否必填 说明
access_token String 通过 client_id,client_secret 调用授权服务获得见 获取访问令牌
format String pcm
audio String 音频数据 base64(单声道,采样率16K,位深16 位,pcm音频,最短1秒,最长60秒)
scoreThreshold float 比对分数设置,得分高于该数值则比对成功,不得低于系统默认值15.0,推荐值30.0
listNum Int 比对返回声纹条数
vad Int 是否打开vad(语音端点检测)处理,默认为关闭
打开vad功能可以提升声纹识 别准确度,但会增加响应时间
1:打开
0:关闭

请求示例

curl -X POST -H"Content-Type:application/json"
https://openapi.data-baker.com/vpr/search
-d '{"access_token" : "eyJ...","format" : "pcm","audio" : "AAAAAA","scoreThreshold":30.0,"listNum":5}'

响应结果

content_type 为 application/json

返回数据为 json 格式,err_msg 字段为 错误信息

参数名称 类型 说明
err_msg String 错误信息
err_no String 错误码
log_id String 日志标识
matchList Array 返回结果数据

matchList参数

参数名称 类型 说明
pkid String 匹配到的声纹特征 id
score float 比对的分数
name String 声纹关联名字

返回示例

    {
     "log_id": "1637153028866860",
     "err_msg": "SUCCESS",
     "matchList": [
        {
         "spkid": "3bc084c0-a0ea-4fe2-9b1b-358c74b21c8b",
         "score": 63.936468236333987,
         "name": "1"
        },
        {
         "spkid": "70532bab-0cce-4d23-af07-4f18bb94b928",
         "score": 61.937236514386112,
         "name": "2"
        },
        {
         "spkid": "7dbf40f6-db6c-4b35-9740-387e3bdbe657",
         "score": 59.941546517333543,
         "name": "3"
        }
      ],
     "err_no": 90000
    }
      

JAVA示例代码

package com.databaker.web.asr;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;

import java.io.File;
import java.io.FileInputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * 声纹识别RESTFUL API接口调用示例
 * 附:声纹识别RESTFUL API文档 【https://www.data-baker.com/specs/file/vpr_api_restful】
 *
 * 注意:
 * 1.仅作为demo示例,失败重试、token过期重新获取、日志打印等优化工作需要开发者自行完成
 * 2.此demo将6个接口一次性封装,请参照接口文档,使用时只需在main中逐一解开方法注释,并补充方法中的参数值即可
 *
 * @author data-baker
 */
public class VoiceprintRecognitionDemo {

    /**
     * 授权:需要在开放平台获取【https://ai.data-baker.com/】
     */
    private static final String clientId = "";
    private static final String clientSecret = "";
    /**
     * 获取token的地址信息
     */
    public static String tokenUrl = "https://openapi.data-baker.com/oauth/2.0/token?grant_type=client_credentials&client_secret=%s&client_id=%s";

    /** 创建声纹ID API地址 */
    private static String createUrl = "https://openapi.data-baker.com/vpr/createid";
    /** 声纹注册API地址 */
    private static String registUrl = "https://openapi.data-baker.com/vpr/register";
    /** 查询声纹状态码API地址 */
    private static String queryStatusUrl = "https://openapi.data-baker.com/vpr/status";
    /** 删除声纹API地址 */
    private static String deleteUrl = "https://openapi.data-baker.com/vpr/delete";
    /** 声纹验证(1:1)API地址 */
    private static String matchUrl = "https://openapi.data-baker.com/vpr/match";
    /** 声纹对比(1:N)API地址 */
    private static String searchUrl = "https://openapi.data-baker.com/vpr/search";

    public static void main(String[] args){
        try {
            /** 创建声纹ID */
//        doCreateLibrary();
            /** 声纹注册 */
//            doRegist();
            /** 查询声纹状态码 */
//        doQueryStatus();
            /** 删除声纹 */
//        doDelete();
            /** 声纹验证(1:1) */
//        doMatch();
            /** 声纹验证(1:N) */
//        doSearch();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void doCreateLibrary() {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        String rightResultdesc = "创建声纹库完成,结果信息";
        String wrongResultdesc = "创建声纹库失败,结果信息";
        sendReqUtil(params,createUrl,rightResultdesc,wrongResultdesc);
    }

    public static void doRegist() throws Exception {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        params.put("format","pcm");
        params.put("audio",encodeBase64File(""));  //获取音频数据地址
        params.put("registerId","");                    //声纹库id
        params.put("name","声纹注册测试");                //自定义名字
        params.put("scoreThreshold", 65.0);             //注册有效分数
        String rightResultdesc = "声纹注册完成,结果信息";
        String wrongResultdesc = "声纹注册失败,错误信息";
        sendReqUtil(params,registUrl,rightResultdesc,wrongResultdesc);
    }

    private static void doQueryStatus() {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        params.put("registerId","");                    //声纹库id
        String rightResultdesc = "查询声纹状态码完成,结果信息";
        String wrongResultdesc = "查询声纹状态码失败,结果信息";
        sendReqUtil(params,queryStatusUrl,rightResultdesc,wrongResultdesc);
    }

    private static void doDelete() {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        params.put("registerId","");                    //声纹库id
        String rightResultdesc = "删除声纹完成,结果信息";
        String wrongResultdesc = "删除声纹失败,结果信息";
        sendReqUtil(params,deleteUrl,rightResultdesc,wrongResultdesc);
    }

    public static void doMatch() throws Exception {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        params.put("format","pcm");
        params.put("audio",encodeBase64File("")); //获取音频数据地址
        params.put("scoreThreshold",30.0);             //分数阈值
        params.put("matchId","");                      //声纹库id
        String rightResultdesc = "声纹1:1验证完成,结果信息";
        String wrongResultdesc = "声纹1:1验证失败,结果信息";
        sendReqUtil(params,matchUrl,rightResultdesc,wrongResultdesc);
    }

    public static void doSearch() throws Exception {
        Map<String,Object> params = new HashMap<>();
        params.put("access_token",getAccessToken());
        params.put("format","pcm");
        params.put("audio",encodeBase64File("")); //获取音频数据地址
        params.put("scoreThreshold",30.0);             //分数阈值
        params.put("listNum",5);
        String rightResultdesc = "声纹1:N验证完成,结果信息";
        String wrongResultdesc = "声纹1:N验证失败,结果信息";
        sendReqUtil(params,searchUrl,rightResultdesc,wrongResultdesc);
    }

    public static String encodeBase64File(String path) throws Exception {
        File file = new File(path);
        FileInputStream inputFile = new FileInputStream(file);
        byte[] buffer = new byte[(int) file.length()];
        inputFile.read(buffer);
        inputFile.close();
        return Base64.getEncoder().encodeToString(buffer);
    }

    private static void sendReqUtil(Map<String,Object> params,String url,String rightResultdesc,String wrongResultdesc){
        try {
            OkHttpClient client = new OkHttpClient().newBuilder()
                    .connectTimeout(60, TimeUnit.SECONDS)
                    .readTimeout(60, TimeUnit.SECONDS)
                    .writeTimeout(60, TimeUnit.SECONDS)
                    .build();
            MediaType mediaType = MediaType.parse("application/json");
            RequestBody body = RequestBody.create(JSONObject.toJSONString(params),mediaType);
            //构造request
            Request request = new Request.Builder()
                    .url(url)
                    .method("POST", body)
                    .addHeader("Content-Type", "application/json")
                    .build();
            Response response = null;
            response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                JSONObject jsonObject = JSON.parseObject(response.body().string());
                System.out.println(rightResultdesc + ": " + (jsonObject == null ? "" : jsonObject));
            } else {
                System.out.println(wrongResultdesc + ": " + response.body().string());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getAccessToken() {
        String accessToken = "";
        OkHttpClient client = new OkHttpClient();
        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;
    }
}
      

Python示例代码

import requests
import json
import argparse
import base64
import os
import time


class VoicePrint:

    # 获取声纹id
    def get_voiceprint_id(self, access_token):
        url = "https://openapi.data-baker.com/vpr/createid"
        headers = {'Content-Type': 'application/json'}
        data = {'access_token': access_token}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        register_id = json.loads(response.text).get("registerid")
        if json.loads(response.text).get('err_no') == 90000:
            return register_id
        else:
            raise Exception

    # 声纹注册
    def voiceprint_register(self, audio, access_token, name, format, registerId):
        url = 'https://openapi.data-baker.com/vpr/register'
        headers = {'Content-Type': 'application/json'}
        data = {'access_token': access_token,
                'format': format,
                'audio': audio,
                'registerId': registerId,
                'name': name,
                'scoreThreshold': 30.0}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        if json.loads(response.text).get('err_no') == 90000:
            return True
        else:
            print(response.text)
            return False

    # 查询声纹状态码
    def check_voiceprint_status(self, access_token, register_id):
        url = 'https://openapi.data-baker.com/vpr/status'
        headers = {'Content-Type': 'application/json'}
        data = {'access_token': access_token,
                'registerId': register_id}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        if json.loads(response.text).get('err_no') == 90000:
            if json.loads(response.text).get('status') == 3:
                return "register successfully"
            else:
                return "register failed"
        else:
            raise Exception

    # 声纹删除
    def remove_voiceprint(self, access_token, registerId):
        url = 'https://openapi.data-baker.com/vpr/delete'
        headers = {'Content-Type': 'application/json'}
        data = {'access_token': access_token,
                'registerId': registerId}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        if json.loads(response.text).get('err_no') == 90000:
            return "remove successfully"
        else:
            return "remove failed"

    # 声纹对比
    def verification_1VN(self, access_token, file):
        url = 'https://openapi.data-baker.com/vpr/search'
        headers = {'Content-Type': 'application/json'}

        data = {'access_token': access_token,
                'format': args.format,
                'audio': file,
                'listNum': 10,
                'scoreThreshold': 65.0}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        return response

    # 声纹认证
    def verification_1V1(self, access_token, file, matchId):
        url = 'https://openapi.data-baker.com/vpr/match'
        headers = {'Content-Type': 'application/json'}
        data = {'access_token': access_token,
                'format': 'pcm',
                'audio': file,
                'matchId': matchId,
                'scoreThreshold': 65.0}
        response = requests.post(url, data=json.dumps(data), headers=headers)
        return response


# 获取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 get_args():
    parser = argparse.ArgumentParser(description='VR')
    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('-name', type=str, required=True)
    parser.add_argument('--format', type=str, required=False, default='pcm')
    parser.add_argument('--scoreThreshold', type=float, required=False, default=65.0)

    args = parser.parse_args()

    return args


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

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

        # 创建声纹特征id
        registerId = vp.get_voiceprint_id(access_token)

        num_of_registered_audio = 0
        for root, dirs, files in os.walk(file_path):
            for file in files:
                with open(os.path.join(file_path, file), 'rb') as f:
                    audio = str(base64.b64encode(f.read()), encoding='utf-8')
                # 声纹注册
                if vp.voiceprint_register(audio, access_token, args.name, args.format, registerId):
                    num_of_registered_audio += 1
                if num_of_registered_audio >= 3:
                    print("register successfully")
                    break

        time.sleep(1)

        with open('data/1.wav', 'rb') as f:
            file = str(base64.b64encode(f.read()), encoding='utf-8')

        # 声纹对比(1 V N)
        response = vp.verification_1VN(access_token, file)
        print(response.text)

        # 声纹验证(1 V 1)
        # response = vp.verification_1V1(access_token, file, registerId)
        # print(response.text)

        # 查询声纹注册状态
        # print(vp.check_voiceprint_status(access_token, registerId))

        # 删除指定声纹
        # print(vp.remove_voiceprint(access_token, registerId))

        print('finished')

    except Exception as e:
        print(e)


      

命令行执行

python voiceprint.py -client_secret=您的client_secret -client_id=您的client_id -file_path=文件夹路径 -name=声纹名称

错误码

错误码分类

err_no 描述
100xx 请求参数错误
200xx 链接服务器错误
300xx 业务调用错误
400xx 引擎内部错误
500xx 授权相关错误

详细错误码

err_no 描述
90000 成功
10001 请求参数错误
10002 请求体格式错误
10003 请求头错误
20001 数据库错误
20002 资源请求错误
20003 REDIS数据库错误
30001 语音过长错误
30002 语音过短错误
30003 语音数据错误
30004 调用数量已达上限
30005 并发超出限制
30006 声纹ID未找到
30007 声纹ID不属于该账户
30008 声纹ID已经注册
30009 声纹ID未注册
30010 声纹得分低于阈值
30011 得分阈值设置低于默认值
30012 声纹数量已达上限
40001 创建声纹错误
40002 提取特征错误
40003 声纹匹配错误
50001 校验token错误
50002 token无效错误