對於語音識別,一般有實時語音識別和語音文件的識別處理等方式,如在會議、培訓等場景中,可以對錄製的文件進行文字的轉錄,對於轉錄文字的成功率來說,如果能夠轉換90%以上的正確語音內容,肯定能減輕很多相關語音文本編輯的繁瑣工作,而目前大多數語音轉錄的介面基本都能夠保證在這個成功率上,有些甚至超過98%以上... ...
對於語音識別,一般有實時語音識別和語音文件的識別處理等方式,如在會議、培訓等場景中,可以對錄製的文件進行文字的轉錄,對於轉錄文字的成功率來說,如果能夠轉換90%以上的正確語音內容,肯定能減輕很多相關語音文本編輯的繁瑣工作,而目前大多數語音轉錄的介面基本都能夠保證在這個成功率上,有些甚至超過98%以上,非常不錯,因為他們對於各種場景的濾波,可以更加提供文字的準確性。本篇隨筆對各種語音開發平臺做一個介紹,並針對依圖語音API的C#封裝以及調用進行語音轉寫進行介紹。
1、語音識別的介面提供商及API情況
語音識別有很多提供商,如常見的百度、阿裡雲、依圖語音等,他們都提供了不同的API介面來實現外部的調用處理,本篇隨筆主要針對依圖語音(號稱能夠識別99%以上的智能轉錄)進行測試,對於其他類型的語音API,由於介面處理方式大同小異,並沒有一一測試。
1)百度語音轉錄
2)阿裡雲語音轉錄
3)依雲語音開發平臺
對於短語音的測試,依圖語音的轉錄基本上在98%以上,偶爾有一兩個詞語文字因為不常見而出錯而已,非常不錯。
由於依圖語音平臺雖然提供了Java的案例代碼,但是沒有對應C #API調用案例,因此需要根據介面的說明進行轉換。
對於依圖語音的API說明,還是介紹的比較詳細的,如下所示。
一般根據這些很容易編寫對應的介面API封裝函數,我這裡主要用來封裝對應的C#調用API。
2、基於依圖語音API的C#封裝
我們針對API進行了封裝,然後在界面上進行測試對應的功能,如下Winform界面測試所示。
一個短句,發現一個錯誤的字,不過整體效果還是比較好,斷句以及內容都算很好的。
這個項目分為三部分,第一是對請求介面數據和返回數據的對象封裝(簡稱DTO對象),第二是對依圖長語音和短語音介面的API介面封裝,包括授權信息的處理;長語音轉寫的任務創建、任務查詢、任務停止幾個部分;以及短語音的轉寫處理。第三是Winform界面的功能測試和日誌處理操作,方便瞭解功能的實際處理情況。
【創建長語音轉錄任務】主要用於演示如何生成簽名並調用介面創建轉寫任務的操作,操作後提示是否成功,並記錄下任務ID,供查詢任務或停止任務使用。同時在日誌和文本框裡面生成相關的JSON數據信息,日誌在運行目錄的log/log.txt中記錄。
對於依圖語音轉換來說,我們一般使用非同步的處理方式,所以更好的是等待任務處理完後回調告訴我們處理結果更好,因此適合於部署Web API的應用,用於讓依圖語音平臺的伺服器進行回調處理結果。
首先第一步我們需要處理API的授權簽名,用於後續介面的調用,我們可以根據簽名的規則進行編寫代碼即可。
/// <summary> /// 簽名處理 /// </summary> public class SignatureHelper { /// <summary> /// 生成授權簽名信息 /// </summary> /// <param name="data"></param> /// <param name="key"></param> /// <returns></returns> public static string CalculateRFC2104HMAC(string data, string key) { key = key ?? ""; var encoding = new System.Text.UTF8Encoding(); byte[] keyByte = encoding.GetBytes(key); byte[] messageBytes = encoding.GetBytes(data); using (var hmacsha256 = new HMACSHA256(keyByte)) { byte[] hashmessage = hmacsha256.ComputeHash(messageBytes); StringBuilder builder = new StringBuilder(); for (int i = 0; i < hashmessage.Length; i++) { builder.Append(hashmessage[i].ToString("x2")); } return builder.ToString(); } } /// <summary> /// 生成請求授權信息 /// </summary> /// <returns></returns> public static AuthRequestDto GetAuthDto() { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", true, reloadOnChange: true); var config = builder.Build(); //讀取配置 var DevId = config["YITU:DevId"]; var DevKey = config["YITU:DevKey"]; var dto = new AuthRequestDto(); dto.DevId = DevId; dto.Timestamp = DateTime.Now.DateTimeToInt(); var accessKey = DevKey; var signKey = dto.DevId + dto.Timestamp; //簽名加密鍵 dto.Signature = SignatureHelper.CalculateRFC2104HMAC(signKey, accessKey); return dto; } /// <summary> /// 對請求的HttpClient設置相關的授權請求Header信息 /// </summary> /// <param name="client"></param> /// <param name="dto"></param> public static void SetSigature(HttpClient client, AuthRequestDto dto) { client.DefaultRequestHeaders.Add("x-dev-id", dto.DevId); client.DefaultRequestHeaders.Add("x-request-send-timestamp", dto.Timestamp.ToString()); client.DefaultRequestHeaders.Add("x-signature", dto.Signature); client.DefaultRequestHeaders.Add("Date", DateTime.Now.AddHours(-8).ToString("R")); } }
這個按鈕功能,主要測試一下使用輔助類生成的授權認證信息,授權認證信息是根據加密規則構建的簽名信息和賬號信息。
這個主要是演示輔助類生成簽名,並獲得的數據信息:
然後我們定義一個控制器,用於接收依圖語音的伺服器API回調處理,用於記錄轉換的結果內容。
namespace CallBackApi.Controllers { /// <summary> /// 用於接收長語音信息回調的處理 /// </summary> [ApiController] [Route("[controller]")] public class LongVoiceController : ControllerBase
在控制器中編寫存儲的邏輯,寫入資料庫。
/// <summary> /// 回調寫入結果, 路由:post /longvoice /// </summary> /// <param name="input"></param> /// <returns></returns> [HttpPost] public async Task<CommonResultDto> CallBack(LongVoiceResultDto input) { CommonResultDto result = null; var json = JsonConvert.SerializeObject(input, Formatting.Indented); _logger.LogInformation(json); try { var helper = new LongVoiceDbHelper(); var bResult = await helper.SaveData(input); result = new CommonResultDto(0, bResult ? "操作成功" : "操作失敗"); } catch(Exception ex) { result = new CommonResultDto(1, ex.Message); _logger.LogError(ex, ex.Message); } return result; }
我們根據依圖語音的對象模型,構建對應的對象信息屬性,然後保存起來即可。
/// <summary> /// 保存數據到資料庫 /// </summary> /// <param name="dto"></param> /// <returns></returns> public async Task<bool> SaveData(LongVoiceResultDto dto) { bool result = false; if(dto != null) { using(var db = CreateDb()) { var info = new ConsultationInfo(); info.DiscernStatus = dto.taskId; info.OperateStatus = "未識別"; if (dto.data != null && dto.data.speechResult != null) { if (dto.data.statusCode == 3) { info.OperateStatus = "已識別"; } var speechResult = dto.data.speechResult; info.DiscernText = speechResult.resultText; } result = await db.Insertable(info).ExecuteCommandAsync() > 0; } } return result; }
回調介面主要用於長語音任務執行完成後,伺服器的回調處理,我這裡使用.net core5的Web API項目來處理,通過使用Restful規則的API控制處理,接收伺服器的回調數據請求,並把請求數據記錄資料庫或者在log/log.txt文件中。
我們先發起語音轉錄請求,如下代碼所示。
private LongVoiceRequestDto GetVoice1() { var input = new LongVoiceRequestDto() { audioUrl = "https://www.***.com/downloads/iqidi.mp3", //語音文件 callback = "http://www.***.com:8080/longvoice", //回調地址 fileData = new FileData { aue = "mpeg2", audioName = "iqidi.mp3", sampleRateHertz = 16000, lang = "MANDARIN" }, speechConfig = new SpeechConfig { scene = "GENERAL", byWords = true, customWords = new List<string>() { //"開發框架提供商", //"廣州愛奇迪軟體科技有限公司" }, useCustomWordsIds = new List<int>() { }, addPunctuation = true, wordsReplace = true, numOfSpeakers = 1, convertNumber = true, //disfluency = true }, wordsReplace = new List<WordsReplace>() { new WordsReplace() { keywords = "他媽的", replace = "*" }, new WordsReplace() { keywords = "破壞", replace = "##" } } }; return input; }
對於長語音的轉換,我們只是發起請求,有時候需要等待一點時間,伺服器才會根據請求的回調地址進行會寫操作的。發起長語音的請求如下代碼所示。
private async void btnTransfer_Click(object sender, EventArgs e) { try { var input = this.radSmall.Checked ? GetVoice1() : GetVoice2(); var result = await longApi.Transfer(input); if (result != null) { this.txtTaskId.Text = result.taskId;//任務ID,可供查詢,停止 MessageUtil.ShowTips($"任務創建{(result.rtn == 0 ? "成功" : "異常:" + result.message)},任務ID:{result.taskId}"); } var json = JsonConvert.SerializeObject(result, Formatting.Indented); this.richLog.AppendText(json); this.richLog.AppendText(Environment.NewLine); Serilog.Log.Information(json); } catch(Exception ex) { MessageUtil.ShowError(ex.Message); } }
回調介面主要用於長語音任務執行完成後,伺服器的回調處理。
而如果是短語音轉寫,就和我們前面說到的一樣,馬上就可以出結果了。
private async void btnShort_Click(object sender, EventArgs e) { try { var input = GetShortVoice(); var result = await shortApi.Transfer(input); if (result != null) { MessageUtil.ShowTips($"短語音聽寫, 操作{(result.rtn == 0 ? "成功" : "異常:" + result.message)}"); } var json = JsonConvert.SerializeObject(result, Formatting.Indented); this.richLog.AppendText(json); this.richLog.AppendText(Environment.NewLine); Serilog.Log.Information(json); } catch (Exception ex) { MessageUtil.ShowError(ex.Message); } }
我們只需要把返回的結果信息,轉換為相關的模型對象,然後進行顯示或者存儲即可完成。
項目可以通過VS發佈方式發佈一個文件包,部署到伺服器上即可。
配置項目後臺一直運行。
以上就是關於依圖語音的測試處理,對應後端的回調處理,我們可以轉錄長語音文件,不過依圖語音平臺對於身份的審核比較嚴格,也是收費的API(其他阿裡、百度也都是),因此在商用的時候,需要考慮好即可。
主要研究技術:代碼生成工具、會員管理系統、客戶關係管理軟體、病人資料管理軟體、Visio二次開發、酒店管理系統、倉庫管理系統等共用軟體開發
專註於Winform開發框架/混合式開發框架、Web開發框架、Bootstrap開發框架、微信門戶開發框架的研究及應用。
轉載請註明出處:
撰寫人:伍華聰 http://www.iqidi.com