# 聲紋識別
[TOC]
聲紋識別(Voiceprint Recognize),是一項提取說話人聲音特征和說話內容信息,自動核驗說話人身份的技術。MSC SDK 聲紋識別(IdentityVerfier)的使用包括注冊(訓練)、驗證和模型操作。類似于一個網站的用戶登錄一樣,用戶必須先注冊,才能登錄(驗證),在用戶忘記密碼時,可以提供重設密碼的操作(模型操作)。
聲紋使用過程的主要參數有:
* 用戶ID(AUTH_ID):標識每個使用聲紋功能的終端用戶的唯一ID
注:長度為6-18個字符(由英文字母、數字、下劃線組成,不能以數字開頭),不支持中文字符。
* 業務類型(MFV_SST):用來標識本次會話是注冊還是驗證
* 密碼類型(MFV_PWDT)
* 密碼(MFV_PWD):進行聲紋注冊(訓練)時傳入的密碼
* 模型操作命令(CMD):進行聲紋模型查詢和刪除
* 注冊次數(MFV_RGN):聲紋訓練次數
不同 APPID 的用戶 ID 相互獨立,即不同的 APPID 可以用相同的用戶 ID——他們注冊的模型也相互獨立。如果您的項目使用了多個appid(例如分Android和iOS兩個app版本),需要多個appid的用戶id數據打通,可以通過文章末尾的技術支持聯系方式與我們聯系。
## 聲紋注冊
目前 MSC SDK 支持兩種類型的聲紋密碼:數字密碼和文本密碼。文本密碼的效果在優化中,建議使用數字密碼。密碼類型的取值說明如下表所示:
| 取值 | 說明 |
| --- | --- |
| 1 | 文本密碼。用戶通過讀出指定的文本內容來進行聲紋注冊和驗證,現階段不支持。 |
| 2 | 自由說。用戶通過錄入一段任意20s以上音頻進行注冊,驗證時錄入任意5s以上音頻即可完成驗證,現階段不支持。 |
| 3 | 數字密碼。從云端拉取若干組特定的數字串(默認有5組,每組8位數字),用戶依次讀出這5組數字進行注冊,在驗證過程中會生成一串特定的數字,用戶通過讀出這串數字進行驗證。 |
注冊時使用的密碼通過調用 getPasswordList 方法獲取:
~~~
// 設置會話場景
mIdVerifier.setParameter(SpeechConstant.MFV_SCENES, "ivp");
// 子業務執行參數,若無可以傳空字符傳
StringBuffer params = new StringBuffer();
// 設置模型操作的密碼類型
params.append("pwdt=" + mPwdType + ",");
// 執行密碼下載操作
mIdVerifier.execute("ivp", "download", params.toString(), mDownloadPwdListener);
~~~
通過 mDownloadPwdListener 回調中獲取的密碼,進行聲紋注冊。
~~~
// 設置會話場景
mIdVerifier.setParameter(SpeechConstant.MFV_SCENES, "ivp");
// 設置會話類型
mIdVerifier.setParameter(SpeechConstant.MFV_SST, "enroll");
// 設置訓練次數(可以不做設置,sdk中默認設置為5次)
mIdVerifier.setParameter(SpeechConstant.MFV_RGN, "5");
// 用戶id
mIdVerifier.setParameter(SpeechConstant.AUTH_ID, authid);
// 設置監聽器,開始會話
mIdVerifier.startWorking(mEnrollListener);
~~~
應用通過 mEnrollListener的 onResult 方法來處理注冊結果。在結果result中攜帶了一個返回碼(0表示成功,-1為失敗)和錯誤碼,用來判別注冊是否成功以及出錯原因,錯誤碼的含義如下:
|錯誤碼|數值|說明|
| :---: | :---: | :---: |
|MSS_ERROR_IVP_GENERAL|11600|正常,請繼續傳音頻|
|MSS_ERROR_IVP_EXTRA_RGN_SOPPORT|11601|rgn超過最大支持次數9|
|MSS_ERROR_IVP_TRUNCATED|11602|音頻波形幅度太大,超出系統范圍,發生截幅|
|MSS_ERROR_IVP_MUCH_NOISE|11603|太多噪音|
|MSS_ERROR_IVP_TOO_LOW|11604|聲音太小|
|MSS_ERROR_IVP_ZERO_AUDIO|11605|沒檢測到音頻|
|MSS_ERROR_IVP_UTTER_TOO_SHORT|11606|音頻太短|
|MSS_ERROR_IVP_TEXT_NOT_MATCH|11607|音頻內容與給定文本不一致|
結果中包含的字段以及各字段的含義見附錄。
## 聲紋驗證
聲紋驗證過程與聲紋注冊類似,不同之處僅在于MFV_SST需要設置為“verify”,且不用設置 MFV_RGN 參數,并且,在數字密碼類型時,密碼通過 VerifierUtil.generateNumberPassword 生成。
其他參數的設置、驗證結果的處理過程完全可參考上一節。
另外,為了達到較好的效果,請在聲紋注冊與驗證過程中盡量與麥克風保持同樣的距離(建議的最佳距離是15厘米左右)。如果距離差距較大的話,可能會對驗證通過率產生較大影響。
## 模型操作
聲紋注冊成功后,在語音云端上會生成一個對應的模型來存儲聲紋信息,聲紋模型的操作即對模型進行查詢和刪除。
~~~
// 設置會話場景
mIdVerifier.setParameter(SpeechConstant.MFV_SCENES, "ivp");
// 用戶id
mIdVerifier.setParameter(SpeechConstant.AUTH_ID, authid);
// 子業務執行參數,若無可以傳空字符傳
StringBuffer params3 = new StringBuffer();
// 設置模型操作的密碼類型
params3.append("pwdt=" + mPwdType + ",");
// 執行模型操作,cmd 取值為"query","delete",分別表示查詢和刪除
mIdVerifier.execute("ivp", cmd, params3.toString(), mModelListener);
~~~
## 安全性問題
從上文的3個小節可以看到,對應用來說,操作聲紋都是很簡單直接的。因此,有些安全性也是應用應該考慮的:
* 更新模型:
應用在給用戶更新聲紋模型等操作時,為了安全性,應該考慮必要的驗證,如,必須先通過聲紋密碼或應用登錄密碼驗證,才能進行下一步更新聲紋模型(重新注冊)——類似修改密碼時,必須先進行安全性驗證一樣。
* APPID:
從前面的特征可以看到,如果 APPID 與 libmsc.so 泄漏后,使用這個 APPID 和 libmsc.so 就可以繞過應用層的安全驗證,操作該 APPID 的所有用戶ID的模型。所以,應用的 APPID 須保證不泄漏給他人——如不要以明文方式在代碼中以字符串保存;在論壇發帖求助時,不要在所有瀏覽者都可見的正文中帶 APPID 內容等。
* 用戶ID:
SDK 對通過驗證 APPID 的應用,只要指定用戶 ID 就可以進行更新模型操作(先刪除,再注冊,或注冊時指定替換)。所以,應用應當考慮用戶可能會惡意指定他人的用戶 ID,進行注冊或驗證的情況。應用可以在展示給用戶的賬號和用來注冊 MSC SDK 聲紋的用戶 ID 間,做一層映射,**使用戶無法直接看到或猜測到**實際用于 MSC SDK 聲紋時的用戶 ID 值;同時,應用在用戶操作聲紋密碼的頁面中,應盡可能的把賬號設置為只讀——避免惡意修改他人賬號聲紋密碼的情況。
* 驗證密碼:
因為人的聲音是可以錄制下來的,當驗證的密碼固定不變時,用戶的聲音就比較大可能被別人錄制下來,然后再次用來驗證——在密碼相同時。所以,用來驗證的密碼時,每次都不一樣時,安全性可以更大的提搞——隨機數字密碼,比固定文本密碼更安全。同時,也應該提醒用戶,在注意聲音的泄漏或被盜用——如留意不要隨意輸入銀行卡密碼一樣。
* 1:N檢索:
鑒別與驗證的過程相似,不過鑒別需要設置組 ID,以指定要鑒別的組。
其參數設置如下:
~~~
// 設置業務場景
mIdVerifier.setParameter( SpeechConstant.MFV_SCENES, scene );
// 設置業務類型:鑒別(identify)
mIdVerifier.setParameter( SpeechConstant.MFV_SST, "identify" );
// 設置監聽器,開始會話
mIdVerifier.startWorking( listener );
// 指定組id,最相似結果數
String params = "group_id="+groudID
while( !isDataFinished ){
// 寫入數據
mIdVerifier.writeData( scence, params, data, offset, length );
}
mIdVerifier.stopWrite( scence );
~~~
檢索結果通過 listener 的回調返回,應用可通過返回結果中,排在最前面,且相似度超過一定值的,認為數據屬于此用戶 ID。另該功能具體的調用示例可參考身份驗證下載包中的demo部分。