语音识别已经成为人工智能应用的一个重点,通过语音控制设备简单方便,在各个领域兴起了研究应用的热潮。数据、算法及芯片是语音识别技术的3个关键,大量优质的数据、精准快速的算法和高性能语音识别芯片是提升语音识别的核心。语音是人工智能产品的主要入口,乃兵家必争之地也。相关算法研究日新月异,CNN RNN CLRNN HMM LACE等模型都尤其优势,将多种算法综合运用修改更佳。
目前语音识别在智能家居、智能车载、智能客服机器人方面有广泛的应用,未来将会深入到学习、生活、工作的各个环节。国内外许多大公司都在倾力研究此技术,并不断推出实际产品。比如科大讯飞的翻译器译呗,可实现汉语与各种语言之间的互译,效果不错。
百度借助自己的人工智能生态平台,推出了智能行车助手CoDriver。科大讯飞与奇瑞等汽车制造商合作,推出了飞鱼汽车助理,推进车联网进程。搜狗与四维图新合作推出了飞歌导航。云知声、思必驰在导航、平视显示器等车载应用方面推出了多款智能语控车载产品。出门问问则基于自己的问问魔镜进入到智能车载市场。
在语音识别的商业化落地中,需要内容、算法等各个方面的协同支撑,但是良好的用户体验是商业应用的第一要素,而识别算法是提升用户体验的核心因素。下文将从语音识别的算法发展路径、算法发展现状及前沿算法研究三个方面来探讨语音识别技术。
对于语音识别系统而言,第一步要检测是否有语音输入,即,语音激活检测(VAD)。在低功耗设计中,相比于语音识别的其它部分,VAD采用always on的工作机制。当VAD检测到有语音输入之后,VAD便会唤醒后续的识别系统。主要包括特征提取、识别建模及模型训练、解码得到结果几个步骤。
首先,我们知道声音实际上是一种波。常见的mp3、wmv等格式都是压缩格式,必须转成非压缩的纯波形文件来处理,比如Windows PCM文件,也就是俗称的wav文件。wav文件里存储的除了一个文件头以外,就是声音波形的一个个点了。下图是一个波形的示例。
在开始语音识别之前,有时需要把首尾端的静音切除,降低对后续步骤造成的干扰。这个静音切除的操作一般称为VAD,需要用到信号处理的一些技术。要对声音进行分析,需要对声音分帧,也就是把声音切开成一小段一小段,每小段称为一帧。分帧操作一般不是简单的切开,而是使用移动窗函数来实现,这里不详述。帧与帧之间一般是有交叠的,就像下图这样:
图中,每帧的长度为25毫秒,每两帧之间有25-10=15毫秒的交叠。我们称为以帧长25ms、帧移10ms分帧。图中,每帧的长度为25毫秒,每两帧之间有25-10=15毫秒的交叠。我们称为以帧长25ms、帧移10ms分帧。
分帧后,语音就变成了很多小段。但波形在时域上几乎没有描述能力,因此必须将波形作变换。常见的一种变换方法是提取MFCC特征,根据人耳的生理特性,把每一帧波形变成一个多维向量,可以简单地理解为这个向量包含了这帧语音的内容信息。这个过程叫做声学特征提取。实际应用中,这一步有很多细节,声学特征也不止有MFCC这一种,具体这里不讲。
至此,声音就成了一个12行(假设声学特征是12维)、N列的一个矩阵,称之为观察序列,这里N为总帧数。观察序列如下图所示,图中,每一帧都用一个12维的向量表示,色块的颜色深浅表示向量值的大小。
接下来就要介绍怎样把这个矩阵变成文本了。首先要介绍两个概念:
注册百度AI开放平台,点击左侧栏语音技术,在控制栏创建应用:百度AI平台
相关文件:16k.pcm (百度ai平台下载)
百度API提供两种类型的语音识别功能,故语音存储可有两种存储方式:
spring.datasource.url=jdbc:mysql://localhost:3306/ass_test?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=UTC
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
创建fileinfo表
CREATE TABLE `fileinfo` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`filename` varchar(50) NOT NULL COMMENT '文件名',
`filepath` varchar(50) NOT NULL COMMENT '文件路径',
`filetype` varchar(50) NOT NULL COMMENT '文件类型',
`filedata` MEDIUMBLOB COMMENT '文件DATA',
`creattime` datetime COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
汉字转语音播放:
文件识别:
在此之前,需要导入百度api的jar包。
Mave配置:
com.baidu.aip
java-sdk
4.1.1
org.springframework.boot
spring-boot-starter-jdbc
mysql
mysql-connector-java
runtime
public class AipSpeechClient {
//设置APPID/AK/SK
private static final String APP_ID = "";
private static final String API_KEY = "";
private static final String SECRET_KEY = "";
public static AipSpeech AIPSPEECH=null;
private static AipSpeechClient aipSpeechClient;
private AipSpeechClient(){
}
public static AipSpeechClient getInstance(){
if(aipSpeechClient==null){
AIPSPEECH=new AipSpeech(APP_ID, API_KEY, SECRET_KEY);
AIPSPEECH.setConnectionTimeoutInMillis(2000);
AIPSPEECH.setSocketTimeoutInMillis(60000);
aipSpeechClient = new AipSpeechClient();
}
return aipSpeechClient;
}
}
或者创建配置类AppConfig.java,代码如下:
@Configuration
public class AppConfig {
//设置APPID/AK/SK
private static final String APP_ID = "";
private static final String API_KEY = "";
private static final String SECRET_KEY = "";
@Bean
public AipSpeech aipSpeech() {
return new AipSpeech(APP_ID, API_KEY, SECRET_KEY);
}
}
Controller层用@Autowired注入。
/**
* 语音识别controller
*
* @author zhangjx
* @version 1.0
* @since 2019-9-4
*/
@RestController
@RequestMapping("/voice")
public class VoiceReceiveController {
public static final String path = "E:\\testFile\\";
// public AipSpeech client = AipSpeechClient.getInstance().AIPSPEECH;
public static final String filePath = "E:\\testFile\\16k.pcm";
@Autowired
public AipSpeech aipSpeech;
@Autowired
public JdbcTemplate jdbcTemplate;
/**
* 测试demo,直接存入本地,业务环境需要创建表来存储文件名、文件类型及文件路径 此方法亦可存储其他类型文件
*
* @param pcmFile
* @param request
* @return
* @throws IOException
*/
@PostMapping(value = "/receiveToHost")
public String uploadToHost(MultipartFile pcmFile, HttpServletRequest request) throws IOException {
long startTime = System.currentTimeMillis(); //获取开始时间
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("pcmFile");
savePic(file.getInputStream(), file.getOriginalFilename());
String sql = "insert into fileinfo (filename,filepath,filetype,filedata,creattime) values(?,?,?,?,?);";
jdbcTemplate.update(sql, file.getOriginalFilename(), path, file.getOriginalFilename().split("\\.")[1], null,
new Date());
long endTime = System.currentTimeMillis(); //获取结束时间
return "success!"+"程序运行时间:" + (endTime - startTime) + "ms";
}
/**
* 测试demo,直接存入数据库,业务环境需要创建表来存储文件名、文件类型及文件路径 此方法也可以存储其他类型文件,文件大小不宜过大。
*
* @param pcmFile
* @param request
* @return
* @throws IOException
*/
@PostMapping(value = "/receiveToBase")
public String uploadToDatabase(MultipartFile pcmFile, HttpServletRequest request) throws IOException {
long startTime = System.currentTimeMillis(); //获取开始时间
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("pcmFile1");
String sql = "insert into fileinfo (filename,filepath,filetype,filedata,creattime) values(?,?,?,?,?);";
jdbcTemplate.update(sql, file.getOriginalFilename(), "DATABASE", file.getOriginalFilename().split("\\.")[1],
file.getInputStream(), new Date());
long endTime = System.currentTimeMillis(); //获取结束时间
return "success!"+"程序运行时间:" + (endTime - startTime) + "ms";
}
/**
* 测试demo,读取本地文件及二进制数据并识别。
*
* @param pcmFile
* @param request
* @return
* @throws IOException
*/
@GetMapping(value = "/voiceToWord")
public String voiceToWorld() throws IOException {
long startTime = System.currentTimeMillis(); //获取开始时间
// 文件读取方式,aipSpeech.asr()方法为多态方法,实际上都是调用的二进制方法,可自行查看api
JSONObject asrRes = aipSpeech.asr(filePath, "pcm", 16000, null);
long endTime = System.currentTimeMillis(); //获取结束时间
return asrRes.get("result").toString()+"程序运行时间:" + (endTime - startTime) + "ms";
}
/**
* 测试demo,上传文件直接识别。
*
* @param pcmFile
* @param request
* @return
* @throws IOException
*/
@PostMapping(value = "/voiceToWordD")
public String voiceToWorldDirect(MultipartFile pcmFile, HttpServletRequest request) throws IOException {
long startTime = System.currentTimeMillis(); //获取开始时间
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("pcmFile2");
JSONObject asrRes = aipSpeech.asr(file.getBytes(), "pcm", 16000, null);
long endTime = System.currentTimeMillis(); //获取结束时间
return asrRes.get("result").toString()+"程序运行时间:" + (endTime - startTime) + "ms";
}
/**
* 测试demo,文件流
*
* @param inputStream
* @param fileName
*
*/
private void savePic(InputStream inputStream, String fileName) {
OutputStream os = null;
try {
byte[] bs = new byte[1024];
int len;
File tempFile = new File(path);
if (!tempFile.exists()) {
tempFile.mkdirs();
}
os = new FileOutputStream(tempFile.getPath() + File.separator + fileName);
while ((len = inputStream.read(bs)) != -1) {
os.write(bs, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
os.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
启动springboot。
浏览器打开html。
依次进行测试并查看数据库及配置的存储位置。
文件上传响应结果:
文件存入数据库响应结果:
直接识别结果:
文件识别结果:
注意事项:
1、 上传需要完整的录音文件,录音文件时长不超过60s。
2、 系统默认为普通话模式,本次调用为非极速模式语音输入法。
3、 原始 PCM 的录音参数必须符合 16k 采样率、16bit 位深、单声道,支持的格式有:pcm(不压缩)、wav(不压缩,pcm编码)、amr(压缩格式)。
4、 上传文件亦适用其他类型文件上传,数据库存储方式不适合大文件存储,系统设置为16M限制。
5、 本次测试基于springboot进行,demo中的AppID、API Key、Secret Key需自行申请。
6、 错误码
7、 接口函数说明
语音识别极速版采用分段阶梯定价方式,调用单价按照自然月累积调用量所落阶梯区间而变化。月初,上月累积的调用量清零,重新开始累积本月调用量。 每账号前50000次调用免费,免费额度用尽后开始计费,价格如下:
月调用量(万次) | 语音识别极速版(元/次) |
---|---|
0<调用次数<=600 | 0.0042 |
600<调用次数<=3000 | 0.0036 |
3000<调用次数<=6000 | 0.0029 |
6000<调用次数<=15000 | 0.0019 |
15000<调用次数 | 0.0014 |
语音识别包含输入法、搜索、粤语、英语、四川话、远场模型。可按天/月购买QPS。价格如下:
QPS购买方式 | 单价(元) |
---|---|
1QPS/天 | 80 |
1QPS/月 | 1400 |
1QPS/年 | 12000 |
说明:若原有QPS默认配额为2,则购买10QPS/月后,该月QPS提升至12。不限调用量。
接口服务 免费调用量额度 QPS限额 计费模式
语音识别 不限制 默认2-10QPS(可通过企业认证提升) 可购买提升QPS
语音识别极速版 每账号共50000次 默认5QPS;开通付费后提升至50QPS 按调用量阶梯计费
注:成功调用与失败调用均算作一次调用,消耗免费额度。
个人创建的应用控制台,企业认证QPS值为10.
调用方法类似于百度api。
计费标准:
优点:
1、 支持语种多。
2、 支持长时间录音识别(5小时内)。
3、 转换精度高。
缺点:
1、 付费。
企业认证10QPS,个人认证2QPS。
优点:
1、 免费。
2、 提供多版本语音识别技术,如语音识别-echo版,语音识别-流式版(AI Lab),语音识别-流式版(WeChat AI),流式版可做到边录编译。
缺点:
1、 echo版单次请求上限15s,只支持普通话。
2、 AI Lab及WeChat AI只支持普通话。
• 实时语音识别服务,按照处理的语音时长计费,可以自助开通后付费或购买预付费资源包。
• 一句话语音识别服务,按照调用次数计费,可以自助开通后付费或购买预付费资源包。
• 录音文件识别服务,按照录音时长计费,可以自助开通后付费或购买预付费资源包。
• 语音合成服务,按照调用次数计费,可以自助开通后付费或购买预付费资源包。
• 超额并发线路费用,商用客户默认提供200路并发,如果客户业务量较大超过200路的,可以自助购买额外并发线路
• 文本自学习定制模型,用于提高客户业务领域的名词句子识别率,可以自助开通
试用版:
• 目前试用版不计费,您可免费试用,如有变化,请关注官网通知;
• 一句话识别、实时语音识别、语音合成在2个并发内每个自然日使用量不限;
• 录音文件识别每个自然日识别时长不超过2小时;
商用版:
• 如果您需要超过2个并发或更大量的录音文件识别接口的时长使用,请您开通商用版;
• 开通商用版之后,默认为后付费模式。购买预付费资源包之后,自动变更为预付费模式,并使用资源包内资源进行抵扣,当预付费资源包内资源使用完之后,会再次变更为后付费模式;
• 商用版(包括预付费模式和后付费模式)按每个自然日实际使用量计费,无免费额度,不使用则不产生费用,若使用则每天结算。北京时间每晚24点,系统将自动对您当天用量进行全量计算和计费,具体账单生成会有延迟;
• 计费规则:
并发数指同一个账号同时在处理的请求数。
一般语音请求的处理都会延续一段时间,例如用户新建一个语音识别请求,持续发送语音数据给服务端,这时并发数就是1;在这个请求处理的同时,这个用户又新建了另一个请求,开始发送语音数据,这时服务端在处理这个账号的2个请求,并发数就变成2。
优点:
1、 识别准确率高。
2、 超快的解码速率。
3、 独创的模型优化工具。
4、 广泛的领域覆盖。
缺点:
1、付费。