依图语音API的C#封装以及调用进行语音转写的处理
对于语音识别,一般有实时语音识别和语音文件的识别处理等方式,如在会议、培训等场景中,可以对录制的文件进行文字的转录,对于转录文字的成功率来说,如果能够转换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(其他阿里、百度也都是),因此在商用的时候,需要考虑好即可。
依图语音API的C#封装以及调用进行语音转写的处理的更多相关文章
- VC6.0 C++ 如何调用微软windows系统SDK 语音API
下载3个语音API安装包 http://www.microsoft.com/en-us/download/details.aspx?id=10121 需要安装微软语音API安装包:SpeechSDK5 ...
- 利用百度语音API进行语音识别。
由于项目需要,这几天都在试图利用百度语音API进行语音识别.但是识别到的都是“啊,哦”什么的,我就哭了. 这里我只是分享一下这个过程,错误感觉出现在Post语音数据那一块,可能是转换问题吧. API请 ...
- 转:基于科大讯飞语音API语音识别开发详解
原文来自于: http://www.52wulian.org/android_voice/ 最近项目需要用到android语音识别,立马就想到科大讯飞,结合官方实例及阅读API文档,初步的完成了And ...
- QT调用百度语音REST API实现语音合成
QT调用百度语音REST API实现语音合成 1.首先点击点击链接http://yuyin.baidu.com/docs/tts 点击access_token,获取access_token,里面有详细 ...
- 在eclipse中API的封装和调用
自己写的API的封装和调用:1.写好api的方法的实现类.2.抽取一个javadoc文档.file->Export->java->javadoc->finish->Yes ...
- <交流贴>android语音识别之科大讯飞语音API的使用
因为最近在研究语音识别,所以借鉴了一下CreAmazing网友的帖子 Android系统本身其实提供有语音识别模块,在它的APIDemo里也有关于语音识别的sample,不过经过大多开发者的真机测 ...
- Atitit. C# java 的api 文件夹封装结构映射总结
Atitit. C# java 的api 文件夹封装结构映射总结 C# java ref System.Reflection System.Type. java.lang.ref concurren ...
- 循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
在前面随笔<循序渐进VUE+Element 前端应用开发(12)--- 整合ABP框架的前端登录处理>介绍了一个系统最初接触到的前端登录处理的实现,但往往对整个系统来说,一般会有很多业务对 ...
- 【python】调用sm.ms图床api接口,实现上传图片并返回url
图床简介 sm.ms网站提供免费的图床服务.单图上传大小限制5MB,每次最多上传10张,支持多种图片链接格式和api接口调用. 获取令牌 注册账号并登录,点击User-Dashboard 点击API ...
随机推荐
- 洛谷P1563 [NOIP2016 提高组] 玩具谜题
题目链接:https://www.luogu.com.cn/problem/P1563 哈哈哈,这个题拿来一读是不是很吃惊hahaha,我刚开始读的时候吓了我一跳,这么长的题干,这么绕的题意,还有下面 ...
- 浅谈.net core如何使用EFCore为一个上下文注类型注入多个实例用于连接主从数据库
在很多一主多从数据库的场景下,很多开发同学为了复用DbContext往往采用创建一个包含所有DbSet<Model>父类通过继承派生出Write和ReadOnly类型来实现,其实可以通过命 ...
- Solution -「UOJ #450」复读机
\(\mathcal{Description}\) Link. 求从 \(m\) 种颜色,每种颜色无限多的小球里选 \(n\) 个构成排列,使得每种颜色出现次数为 \(d\) 的倍数的排列方案 ...
- Flask中本地栈的使用
4种上下文变量 承接上一篇内容.当一个请求到来时,除了request被封装成全局变量之外,还有三个变量也是同样被封装成全局变量,那就是current_app.g.session.上面4个变量之所以能够 ...
- LRU缓存及实现
一.淘汰策略 缓存:缓存作为一种平衡高速设备与低速设备读写速度之间差异而引入的中间层,利用的是局部性原理.比如一条数据在刚被访问过只有就很可能再次被访问到,因此将其暂存到内存中的缓存中,下次访问不用读 ...
- ConcurrentHashMap (jdk1.7)源码学习
一.介绍 1.Segment(分段锁) 1.1 Segment 容器里有多把锁,每一把锁用于锁容器其中一部分数据,那么当多线程访问容器里不同数据段的数据时,线程间就不会存在锁竞争,从而可以有效的提高并 ...
- suse 12 二进制部署 Kubernetets 1.19.7 - 第01章 - 创建CA证书和kubectl集群管理命令
文章目录 1.kubernetes集群部署 1.0.创建CA证书和秘钥 1.0.0.安装cfssl工具 1.0.1.创建根证书 1.0.2.创建证书签名请求文件 1.0.3.生成CA证书和秘钥 1.0 ...
- iceberg合并小文件冲突测试
基于iceberg的master分支的9b6b5e0d2(2022-2-9). 参数说明 1.PARTIAL_PROGRESS_ENABLED(partial-progress.enabled) 默认 ...
- 一、Java 特性和运行机制
目录 Java 特性和优势 Java应用程序的运行机制 JVM.JRE和JDK Java 特性和优势 跨平台/可移植性 核心优势.比如:Java的int型永远是32位,C++(16,32). 安全性 ...
- 思迈特软件Smartbi:专注BI,把产品打造到极致
在企业服务领域,现在的BI(商业智能)无疑是妥妥的风口.不过在20多年前,BI却完全是一幅门庭冷清宾客稀的光景--小型企业高攀不起,大型企业爱答不理. 一些管理者们理所当然地认为,商业是人脑的高阶竞争 ...