SpringBoot对接阿里云的语音识别服务

2019-11-30  本文已影响0人  执着的逗比

阿里云的语音开发文档地址:
https://help.aliyun.com/document_detail/84459.html
以下是我自己的开发流程,可能会有遗漏错误,仅供参考,建议还是跟着开发文档做,毕竟我也是跟着开发文档一步步做的


一、注册开通服务

  1. 进入阿里云官网,注册 阿里云账号。若已有阿里云账号,请看下一步。
  2. 智能语音交互服务页面,点击立即开通
  3. 在跳转后的页面,点击立即购买,购买语音服务。默认开通试用权限,目前公共云用户可免费使用不超过2路并发。
  4. 在阿里云管控台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就可以了。

上一篇下一篇

猜你喜欢

热点阅读