SpringBoot对接阿里云的语音识别服务
阿里云的语音开发文档地址:
https://help.aliyun.com/document_detail/84459.html
以下是我自己的开发流程,可能会有遗漏错误,仅供参考,建议还是跟着开发文档做,毕竟我也是跟着开发文档一步步做的
一、注册开通服务
- 进入阿里云官网,注册 阿里云账号。若已有阿里云账号,请看下一步。
- 到智能语音交互服务页面,点击立即开通。
- 在跳转后的页面,点击立即购买,购买语音服务。默认开通试用权限,目前公共云用户可免费使用不超过2路并发。
- 在阿里云管控台Access Key管理页面创建并获取您的AccessKey ID和AccessKey Secret。您可以使用它们调用智能语音服务。
image.png
二、创建项目
1、登录到控制台,默认首页为我的项目 -> 所有项目概览,因此时还未创建项目,所以在右侧”我的所有项目”显示当前暂无项目。
2、点击界面上创建项目按钮,会弹出创建项目模态框、
3、然后可以在页面上看到新建的项目,其中的项目Appkey是用SDK调用服务时需要提供的信息。
image.png
4、默认选择通用模型,可以根据自己的场景选择其他合适的模型。点击发布上线后,该项目正式生效。
三、运行SDK
安装Maven工具
下载SDK包并解压,demo 解压后,在pom 目录运行mvn package ,会在target目录生成可执行jar nls-example-recognizer-2.0.0-jar-with-dependencies.jar,将此jar拷贝到目标服务器,运行后在jar包同目录生成logs/nls.log。
java -cp nls-example-recognizer-2.0.0-jar-with-dependencies.jar com.alibaba.nls.client.SpeechRecognizerDemo <app-key> <token> [<url>]
因为我的项目只需要一句话语音识别服务,其它我就不多说了。
四、功能实现
1、在pom.xml中添加以下依赖
<dependency>
<groupId>com.alibaba.nls</groupId>
<artifactId>nls-sdk-recognizer</artifactId>
<version>2.1.1</version>
</dependency>
2、将把在之前生成的nls-example-recognizer-2.0.0-jar-with-dependencies.jar复制到 src/main/webapp/lib下
3、准备要识别的音频文件,阿里云上有个例子,直接下载就可以了,当然也可以直接去生成音频文件,推荐迅捷文字转语音软件。
4、代码实现
package com.chd.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import com.alibaba.nls.client.AccessToken;
import com.alibaba.nls.client.protocol.InputFormatEnum;
import com.alibaba.nls.client.protocol.NlsClient;
import com.alibaba.nls.client.protocol.SampleRateEnum;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizer;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerListener;
import com.alibaba.nls.client.protocol.asr.SpeechRecognizerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SpeechRecognizerDemo {
private static final Logger logger = LoggerFactory.getLogger(SpeechRecognizerDemo.class);
private String appKey;
NlsClient client;
String result;
public SpeechRecognizerDemo(String appKey, String id, String secret, String url) {
this.appKey = appKey;
//TODO 重要提示 创建NlsClient实例,应用全局创建一个即可,生命周期可和整个应用保持一致,默认服务地址为阿里云线上服务地址
//TODO 这里简单演示了获取token 的代码,该token会过期,实际使用时注意在accessToken.getExpireTime()过期前再次获取token
AccessToken accessToken = new AccessToken(id, secret);
try {
accessToken.apply();
System.out.println("get token: " + accessToken.getToken() + ", expire time: " + accessToken.getExpireTime());
// TODO 创建NlsClient实例,应用全局创建一个即可
if(url.isEmpty()) {
client = new NlsClient(accessToken.getToken());
}else {
client = new NlsClient(url, accessToken.getToken());
}
} catch (IOException e) {
e.printStackTrace();
}
}
/// 根据二进制数据大小计算对应的同等语音长度
/// sampleRate 仅支持8000或16000
public static int getSleepDelta(int dataSize, int sampleRate) {
// 仅支持16位采样
int sampleBytes = 16;
// 仅支持单通道
int soundChannel = 1;
return (dataSize * 10 * 8000) / (160 * sampleRate);
}
public String process(File file, int sampleRate) {
SpeechRecognizer recognizer = null;
SpeechRecognizerListener listener = new SpeechRecognizerListener() {
//识别出中间结果.服务端识别出一个字或词时会返回此消息.仅当setEnableIntermediateResult(true)时,才会有此类消息返回
@Override
public void onRecognitionResultChanged(SpeechRecognizerResponse response) {
//事件名称 RecognitionResultChanged、 状态码(20000000 表示识别成功)、语音识别文本
System.out.println("name: " + response.getName() + ", status: " + response.getStatus() + ", result: " + response.getRecognizedText());
}
//识别完毕
@Override
public void onRecognitionCompleted(SpeechRecognizerResponse response) {
//事件名称 RecognitionCompleted, 状态码 20000000 表示识别成功, getRecognizedText是识别结果文本
System.out.println("name: " + response.getName() + ", status: " + response.getStatus() + ", result: " + response.getRecognizedText());
result = response.getRecognizedText();
}
@Override
public void onStarted(SpeechRecognizerResponse response) {
System.out.println("task_id: " + response.getTaskId());
}
@Override
public void onFail(SpeechRecognizerResponse response) {
// TODO 重要提示: task_id很重要,是调用方和服务端通信的唯一ID标识,当遇到问题时,需要提供此task_id以便排查
System.out.println("task_id: " + response.getTaskId() + ", status: " + response.getStatus() + ", status_text: " + response.getStatusText());
}
};
try {
// 传递用户自定义参数
String myParam = "user-param";
int myOrder = 1234;
recognizer = new SpeechRecognizer(client, listener);
recognizer.setAppKey(appKey);
//设置音频编码格式 TODO 如果是opus文件,请设置为 InputFormatEnum.OPUS
recognizer.setFormat(InputFormatEnum.PCM);
//设置音频采样率
if(sampleRate == 16000) {
recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_16K);
} else if(sampleRate == 8000) {
recognizer.setSampleRate(SampleRateEnum.SAMPLE_RATE_8K);
}
//设置是否返回中间识别结果
recognizer.setEnableIntermediateResult(true);
//此方法将以上参数设置序列化为json发送给服务端,并等待服务端确认
long now = System.currentTimeMillis();
recognizer.start();
logger.info("ASR start latency : " + (System.currentTimeMillis() - now) + " ms");
FileInputStream fis = new FileInputStream(file);
byte[] b = new byte[3200];
int len;
while ((len = fis.read(b)) > 0) {
logger.info("send data pack length: " + len);
recognizer.send(b);
// TODO 重要提示:这里是用读取本地文件的形式模拟实时获取语音流并发送的,因为read很快,所以这里需要sleep
// TODO 如果是真正的实时获取语音,则无需sleep, 如果是8k采样率语音,第二个参数改为8000
int deltaSleep = getSleepDelta(len, sampleRate);
Thread.sleep(deltaSleep);
}
//通知服务端语音数据发送完毕,等待服务端处理完成
now = System.currentTimeMillis();
// TODO 计算实际延迟: stop返回之后一般即是识别结果返回时间
logger.info("ASR wait for complete");
recognizer.stop();
logger.info("ASR stop latency : " + (System.currentTimeMillis() - now) + " ms");
fis.close();
} catch (Exception e) {
System.err.println(e.getMessage());
} finally {
//关闭连接
if (null != recognizer) {
recognizer.close();
}
}
return result;
}
public void shutdown() {
client.shutdown();
}
public static String getConvertResult(File file,int sampleRate) {
String appKey = ""; // "填写你的appkey";
String id = ""; // "填写你在阿里云网站上的AccessKeyId";
String secret = ""; // "填写你在阿里云网站上的AccessKeySecret";
String url = "wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1"; // 默认即可,默认值:wss://nls-gateway.cn-shanghai.aliyuncs.com/ws/v1
SpeechRecognizerDemo demo = new SpeechRecognizerDemo(appKey, id, secret, url);
String result = demo.process(file, sampleRate);
demo.shutdown();
return result;
}
// public static void main(String[] args) throws Exception {
// String result = getConvertResult();
// System.out.println(result);
// }
}
代码我是直接从阿里云的开发文档复制下来的,然后根据自己的需求进行修改,仅供参考。
五、效果测试
image.png成功将识别语音并将其转成了文字,有一点要注意,貌似这个SDK已经自带logger的jar包,如果你的项目整合了log4j2,那你运行项目的时候是会报错的,不知道怎么搞,我的做法就是把log4j2给去掉了,直接用SpringBoot自带的logger就可以了。