1. 概述

声纹识别技术(Voiceprint Recognition),简称VPR,是生物识别技术的一种,提取说话人的语音身份特征,提供声纹鉴别和声纹确认,也称为说话人识别,有两类,即说话人辨认和说话人确认。不同的任务和应用会使用不同的声纹识别技术,如缩小刑侦范围时可能需要辨认技术,而银行交易时则需要确认技术。声纹识别就是把声信号转换成电信号,再用计算机进行识别。

本文档旨在讲解如何快速地集成灵云VPR功能到开发者应用中。关于各服务接口更详细的说明,请参考灵云SDK开发手册。在集成过程中如有疑问,可登录灵云开发者论坛,查找答案或与其他开发者交流。

1.1 概念解释

对指南中涉及的名词作简要描述,使开发者在阅读开发指南时,对此有一些大致的了解和预备知识的了解。

名称 说明
Session Session用来标记一个能力运行过程的上下文。一个应用最多可同时创建的Session数受到授权的限制
云端识别 由云端服务器提供识别结果的方式。使用云端能力需要加上hci_vpr_cloud_recog模块
本地识别 通过本地运算来得到识别结果的方式。使用本地能力需要加上hci_vpr_local_recog模块和本地资源文件
特征训练(注册) 为提高音频的识别正确率,灵云VPR提供特征训练的方法,通过大量音频的注册训练,可以提高识别的速度和正确率。详见hci_vpr_enroll函数
特征确认 声纹模型注册和训练成功后,可以对音频数据进行校验,以判断用户唯一标识和音频数据是否相符。详见hci_vpr_verify函数
特征辨识 对音频数据校验后,需要对音频数据识别,识别结果以分数形式返回。详见hci_vpr_identity函数

1.2 能力定义(capkey)

VPR 支持多种能力,通过 capkey 区分不同能力的调用和配置。其中常用 capkey 如下所示:

capkey 支持音频格式
vpr.cloud.recog alaw8k8bit
ulaw8k8bit
pcm8k16bit
alaw16k8bit
ulaw16k8bit
pcm16k16bit
vox6k4bit
capkey 模型背景类型 所需本地资源文件
vpr.local.recog iv200_8k
iv200_16k
iv200_digital_8k
iv200_digital_16k
gmm256_iv200.final.ubm
gmm256_iv200.final.ubm.ie
gmm256_iv200.final.ubm.ie.mean
gmm256_iv200.final.ubm.pld
gmm256_iv200.final.conf

其中本地声纹识别资源列表: |资源目录|支持音频格式| |------|-----------| |16k|pcm16k16bit
ulaw16k8bit
alaw16k8bit| |8k|pcm8k16bit
ulaw8k8bit
alaw8k8bit|

1.3 识别流程

2. 能力使用说明

2.1 准备工作

下载声纹识别SDK并解压缩。

如果需要使用本地能力,请下载相应资源包并解压缩。

2.2 使用Android版SDK

  • 必选模块

    • libhci_curl.dll
    • libhci_sys.dll
    • libhci_vpr.dll
  • 云端识别

    • libhci_vpr_cloud_recog.dll
    • libjtopus.dll (根据压缩方式选择)
    • libjtspeex.dll (根据压缩方式选择)
  • 本地识别

    • libhci_vpr_local_recog.dll

3. 能力集成说明

在调用VPR能力之前,需要初始化灵云SDK的SYS通用模块。

3.1 通用模块初始化

在调用能力之前,需要初始化灵云SDK的通用模块。详见灵云SDK开发手册

  • C++示例代码
HCI_ERR_CODE err_code = HCI_ERR_NONE;
//配置串是由"字段=值"的形式给出的一个字符串,多个字段之间以','隔开。字段名不分大小写。
string init_config = "";
//灵云应用序号
init_config += "appKey=1234abcd";
//灵云开发者密钥
init_config += ",developerKey=1234567890";
//灵云云服务的接口地址
init_config += ",cloudUrl=http://api.hcicloud.com:8888";
//授权文件所在路径,保证可写
init_config += ",authpath=../../bin";
//日志的路径
init_config += ",logfilepath=../../bin";
//日志的等级
init_config += ",loglevel=5";
//日志文件的大小
init_config += ",logfilesize=512";
//其他配置使用默认值,不再添加,如果想设置可以参考开发手册
err_code = hci_init( init_config.c_str() );

提示 因灵云SDK8.1使用Visual Studio 2015开发的原因,在windows下的开发运行环境需要确认安装运行组件vc_redist.x64.exe,vc_redist.x86.exe, 具体请参考https://www.microsoft.com/zh-cn/download/details.aspx?id=48145

3.2 授权检测

在初始化灵云SDK的通用模块后,还需要调用授权检测函数获取云端授权。

C++示例代码

//获取过期时间
int64 expire_time;
int64 current_time = (int64)time( NULL );
HCI_ERR_CODE err_code = hci_get_auth_expire_time( &expire_time );
if( err_code == HCI_ERR_NONE )
{
    //获取成功则判断是否过期
    if( expire_time > current_time )
    {
        //没有过期
        printf( "auth can use continue\n" );
        return true;
    }
}
//获取过期时间失败或已经过期
//手动调用更新授权
err_code = hci_check_auth();
if( err_code == HCI_ERR_NONE )
{
    //更新成功
    printf( "check auth success \n" );
    return true;
}
else
{
    //更新失败
    printf( "check auth return (%d)\n", err_code);
    return false;
}

3.3 VPR初始化

  • c++示例代码

// 初始化VPR
HCI_ERR_CODE err_code = HCI_ERR_NONE;

string vpr_init_config = "dataPath=";
vpr_init_config += data_path;
vpr_init_config += ",initCapkeys=";
vpr_init_config += cap_key;
err_code = hci_vpr_init(vpr_init_config.c_str());
if (err_code != HCI_ERR_NONE)
{
    printf("hci_vpr_init return (%d:%s) \n",err_code,hci_get_error_info(err_code);
    return;
} 
printf("HciVprInit Success");
}

3.4 开启会话(session)

VPR 是通过会话(session)来管理识别过程的。在VPR能力初始化成功之后,需要通过开启识别会话来完成识别。

  • C++示例代码
// 启动 VPR Session,此处可以传入userid
string session_config = "capkey=" + capkey;
if (capkey.find("local") != string::npos)
{
    //如果是本地能力,需要添加资源前缀,请根据时间情况指定
    //session_config += ",resPrefix=";
}

if (!realtime.compare("yes"))
{
    session_config += ",realtime=yes";
}

int session_id = -1;
//用户模型路径,默认是授权文件路径
//session_config += ",usermodelpath = e://";
HCI_ERR_CODE err_code = hci_vpr_session_start(session_config.c_str(), &session_id);
if( err_code != HCI_ERR_NONE )
{
    user_id.clear();
    printf("hci_vpr_session_start return (%d:%s) \n",err_code,hci_get_error_info(err_code));
    return;
}
printf( "hci_vpr_session_start success\n" );

3.5 声纹特征训练或注册

在启动会话(session)成功后,即可以进行VPR的声纹特征训练。

  • C++示例代码
//VPR 注册
/*audioformat 有效值:{pcm8k16bit,ulaw8k8bit,alaw8k8bit,
pcm16k16bit, ulaw16k8bit,alaw16k8bit} */
VPR_ENROLL_VOICE_DATA enrollData;
enrollData.uiVoiceDataCount = nEnrollDataCount;
enrollData.psVoiceDataList = enrollItemArray;
string enrollConfig = "audioformat=pcm16k16bit";
if(!user_id.empty())  
{
    enrollConfig += ",userid=" + user_id;
}
printf("hci_vpr_enroll config [%s]\n", enrollConfig.c_str());
VPR_ENROLL_RESULT enrollResult;

//非实时识别
enrollConfig += (",realtime="+realtime);
//VPR云端非实时识别
err_code = hci_vpr_enroll(session_id,&enrollData,enrollConfig.c_str(),
    &enrollResult);
if (err_code != HCI_ERR_NONE)
{
    user_id.clear();
    printf("hci_vpr_enroll return (%d) \n",err_code);
}
else
{
    printf( "hci_vpr_enroll success\n" );
    user_id = enrollResult.pszUserId;
    HciExampleComon::SetSpecialConsoleTextAttribute();
    printf("enroll result is userid=%s\n",user_id.c_str());
    HciExampleComon::SetOriginalConsoleTextAttribute();
    hci_vpr_free_enroll_result(&enrollResult);
}

3.6 声纹特征确认

  • C++示例代码
//非实时识别
//Verify
//audioformat 
//{pcm8k16bit,ulaw8k8bit,alaw8k8bit,pcm16k16bit, ulaw16k8bit,alaw16k8bit}
string verify_config = "audioformat= pcm16k16bit";
verify_config += ",userid=" + user_id;
err_code = hci_vpr_verify(session_id, voiceData.buff_, voiceData.buff_len_,
                            verify_config.c_str(), &verifyResult);
if( err_code != HCI_ERR_NONE )
{
    printf("hci_vpr_verify return (%d) \n",err_code);
}
else
{
    printf( "hci_vpr_verify success\n" );
    HciExampleComon::SetSpecialConsoleTextAttribute();
    printf("the result score is :%d \n",verifyResult.uiScore);
    if (verifyResult.eStatus == VPR_VERIFY_STATUS_MATCH)
    {
        printf( "voice data matches with user id:%s!\n",user_id.c_str() );
    }
    else
    {
        printf("voice data doesn't match with user id:%s !\n",
        user_id.c_str());
    }
    hci_vpr_free_verify_result(&verifyResult);
    HciExampleComon::SetOriginalConsoleTextAttribute();
}

3.7 声纹辨识确认

  • C++示例代码
//audioformat 
//{pcm8k16bit,ulaw8k8bit,alaw8k8bit,pcm16k16bit,ulaw16k8bit,alaw16k8bit}
string identify_config = "audioformat=pcm16k16bit,";
identify_config += "groupid=" + groupId;
printf("hci_vpr_identify config [%s]\n", identify_config.c_str());
//非实时识别
err_code = hci_vpr_identify(session_id, voiceData.buff_, voiceData.buff_len_, 
                                identify_config.c_str(), &identifyResult);
if( err_code != HCI_ERR_NONE )
{
    printf("hci_vpr_identify return (%d) \n",err_code);
    hci_vpr_session_stop(session_id);
    return;
}
printf( "hci_vpr_identify success\n" );
PrintIdentifyResult(identifyResult);
hci_vpr_free_identify_result(&identifyResult);

3.8 结束识别

最后我们需要反初始化,依次关闭会话,终止AFR能力,关闭灵云系统。

  • C++示例代码
//关闭VPR识别会话
errCode = hci_vpr_session_stop(nSessionId);
//终止VPR能力
errCode = hci_vpr_release();
//终止灵云系统
errCode = hci_release();

4. 常用配置说明

VPR支持实时识别模式,即realtime=yes。可以在hci_vpr_session_start传入该参数,启动实时识别session。 以声纹辨识为例:

  • C++示例代码
//实时识别
string identify_config = "audioformat=pcm16k16bit,";
identify_config += "groupid=" + groupId;
int nPerLen = 3200*20;  //传入每段音频长度
int nLen = 0;            // 当前已传入的长度
while (nLen < voiceData.buff_len_)
{
    int nThisLen = 0;
    if( voiceData.buff_len_ - nLen >= nPerLen )
    {
        nThisLen = nPerLen;
    }
    else
    {
        nThisLen = voiceData.buff_len_ - nLen;
    }        
    err_code = hci_vpr_identify(session_id, voiceData.buff_+nLen, nThisLen, 
        identify_config.c_str(), &identifyResult);
    if (err_code == HCI_ERR_PARAM_INVALID)
    {
        printf("hci_vpr_identify return (%d) \n");
        break;
    }
    if( err_code == HCI_ERR_NONE )
    {
        // 检测到末端了,跳出循环
        break;
    }        
    nLen += nThisLen;
}
// 若未检测到端点,但数据已经传入完毕,则需要告诉引擎数据输入完毕
// 或者检测到末端了,也需要告诉引擎,获取结果
if( err_code == HCI_ERR_VPR_REALTIME_WAITING || err_code == HCI_ERR_NONE )
{
    err_code = hci_vpr_identify(session_id, NULL, 0, 
        identify_config.c_str(), &identifyResult);
    if (err_code != HCI_ERR_NONE)
    {
        printf("hci_vpr_identify return (%d) \n");
    }
}
if( err_code == HCI_ERR_NONE )
{
    // 输出识别结果
    PrintIdentifyResult(identifyResult);
    // 释放识别结果
    hci_vpr_free_identify_result(&identifyResult); 
    if( err_code != HCI_ERR_NONE )
    {
        printf( "hci_vpr_free_recog_result return %d\n", err_code );
        hci_vpr_session_stop(session_id);
        return ;
    }
    printf( "hci_vpr_free_recog_result success\n" );
}
else
{
    printf( "hci_vpr_recog failed with %d\n", err_code );
}

5. FAQ

Q: 我运行你们的 SDK 报 19 号错误:START LOG FAILED, 应该如何解决? A: 出现此问题,一般由两种原因造成。

工程文件里引入了中文路径,导致SDK启动时,读写对应的日志路径报错。 日志文件定义的路径由于权限问题不可读写,比如在 Android 平台上运行时,没有 WRITE_EXTERNAL_STORAGE的权限。

Q: 我运行你们的 SDK 报 23 号错误:LOAD_FUNCTION_FROM_DLL FAILED,应该如何解决? A: 这种情况,通常是由于缺库。最常见的场景是使用本地能力的 capkey,如 vpr.loacl.recog,没有将库文件对应组入(我们 SDK 示例程序,与 example 同层有全套库文件,示例程序内默认只组入了云端库),将相关库补齐即可使用。此外,由于 VPR能力引用了第三方的 OPENCV, MKL 库,因此如果第三方库没有拷入,也会导致此问题。

Q: 我运行你们的 SDK 报 14 号错误:LOCAL_RES_MISSING,应该如何解决? A: 本地能力常会遇到此问题,此问题是由于没有组入对应的本地资源文件。请在我们开发者社区下载需求的本地资源(VPR本地模型)等,并将资源文件组入代码 datapath 指定路径,然后再次尝试运行程序。

Q: 我运行你们的 SDK 报 11 号错误:SERVICE_RESPONSE_FAILED ,应该如何解决? A: 此问题原因较为复杂,可能是传入的参数问题与服务器不匹配,如调用私有云时,没有传入 property 等配置项。也可能是服务端内部的返回原因,请联系技术支持排查。

Q: 我运行你们的SDK报 7 号错误:CONFIG_UNSUPPORT ,应该如何解决? A: 与 11号错误类似,还是配置串问题,7 号错误原因为传入了不支持的配置串。请仔细检查各接口传入的所有配置串,并联系技术支持排查。

Q: 我运行你们的SDK报 9 号错误: SERVICE_TIMEOUT ,应该如何解决? A: 这个是因为您请求我们服务器到返回结果的时间,超过了上限。请检查网络环境相关的原因,并协助提供日志。

Q: 我运行你们的 SDK 报 16 号错误: SESSION_INVALID ,应该如何解决? A: 这个需要检查详细的代码调用过程,调用每个能力核心接口时,都是需要传入 sessionid 的,如果在 sessionstart 的时候,已经发生了错误,或者使用的id,并不是 sessionstart 时候创建的,就会返回此错误,请联系技术支持排查。

Q: 我运行你们的 SDK 报 0 号错误: ERROR NONE,应该如何解决? A: SDK 报 0 号错误, ERROR NONE,代表执行成功,请您继续后续的集成。

results matching ""

    No results matching ""