JAVA对接腾讯语音实时识别引擎

简介: JAVA对接腾讯语音实时识别引擎

一、官网地址


语音识别 SDK 概览 - SDK 文档 - 文档中心 - 腾讯云


需要对接的朋友们,需要咨仔细的看一下文档,主要是一些重要参数,但是小编觉得,腾讯的这个SDK 真的不太友好,demo给的也不是很直接,需要我们自己再次封装,并且SDK不能从中央 仓库直接获取,需要我们自己下载源码,自己搞。。。。


二、对接流程


2.1 先搞jar


我们需要从官网地址下载SDK源码,然后将源码导入我们的IDE中,将out文件夹中的real_asr_sdk_1.6.jar 核心jar包导入到我们自己项目中,如果你的项目是maven方式的话,可以参考小编的文档《maven手动将本地jar包加入到本地maven仓库》。然后还需要引入一下辅助jar,也就是 源码中lib文件夹下面的jar,如果项目中已经有对应的jar,可以直接使用,这些jar可以在中央仓库直接下载。


2.2 代码


我才用的是异步回传结果的方式,因为我的上游是一个ws接口,这个接口不断的接受到语音流,然后我调用腾讯的识别接口,将需要识别的语音流添加到任务中,然后在回调函数中获得识别结果。


任务类:

package com.jack.chat.asrtencent.service;
import com.tencent.cloud.asr.realtime.sdk.asyn_sender.ReceiverEntrance;
import com.jack.chat.fs.service.FsService;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import javax.sound.midi.Soundbank;
public class VoiceTask {
    private ReceiverEntrance receiverEntrance;
    private String taskId;
    public VoiceTask(String taskId) {
        this.taskId = taskId;
    }
    /**
     * @Description:
     * @author: zhenghao
     * @date: 2020/8/13 19:00
     */
    public void init(FsService fsService,String tel) {
        System.out.println("初始化成功");
        // 新建一个服务
        this.receiverEntrance = new ReceiverEntrance(Integer.parseInt(taskId));
        // 启动服务
        this.receiverEntrance.start();
        // 注册N个回调Handler
        this.receiverEntrance.registerReponseHandler(new MyResponseHandler(this.taskId,tel,fsService));
        System.out.println("初始化完成");
    }
    /**
     * 创建和启动服务线程。包括:数据添加线程、发送线程、通知线程。
     */
    public void start(byte[] contentStream) {
        receiverEntrance.add(contentStream);
        // 开始添加数据
//    this.voiceAddingTask = new VoiceAddingTask(this.receiverEntrance,contentStream );
//    this.voiceAddingTask.start();
        // 10秒后停止任务/关闭服务。如需一直使用,则不要调用它。
    /*this.sleepSomeTime(10000);
    this.stop();*/
    }
    public void stop() {
        this.receiverEntrance.stopService();
    }
}

核心类:每一个通道我们都需要new 一个核心类

package com.jack.chat.asrtencent.service;
import com.tencent.cloud.asr.realtime.sdk.config.AsrBaseConfig;
import com.tencent.cloud.asr.realtime.sdk.config.AsrGlobelConfig;
import com.tencent.cloud.asr.realtime.sdk.config.AsrInternalConfig;
import com.tencent.cloud.asr.realtime.sdk.config.AsrPersonalConfig;
import com.tencent.cloud.asr.realtime.sdk.model.enums.ResponseEncode;
import com.tencent.cloud.asr.realtime.sdk.model.enums.SdkRole;
import com.tencent.cloud.asr.realtime.sdk.model.enums.VoiceFormat;
import com.tencent.cloud.asr.realtime.sdk.utils.ByteUtils;
import com.jack.chat.fs.service.FsService;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
public class RasrAsynRequestSample {
    private VoiceTask voiceTask;
    private FsService fsService;
    static {
        initBaseParameters();
    }
    public RasrAsynRequestSample(String taskId, VoiceTask voiceTask) {
        this.taskId = taskId;
        this.voiceTask = voiceTask;
    }
    public void init(String tel) {
        System.out.println("开始反射fsservice");
        WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
        this.fsService = (FsService) wac.getBean("fsService");
        System.out.println("反射完成");
        this.voiceTask.init(this.fsService,tel);
    }
    private int threadNumber = 1;
    private String taskId = "0";
//  private String voiceFile = "test_wav/8k/8k.wav";
    private List<VoiceTask> taskList = new ArrayList<VoiceTask>();
    public static void main(String[] args) throws Exception {
        RasrAsynRequestSample rasrRequestSample = new RasrAsynRequestSample("1", new VoiceTask("1"));
        rasrRequestSample.init("18333612608");
        rasrRequestSample.setArguments(args);
        String audio_data = "C:\\data\\8k.wav";
        int subLength = 320;
//        byte[] stream = new byte[320];
//        BufferedInputStream bufferedInputSteam = new BufferedInputStream(new FileInputStream(new File(audio_data)));
//        int len;
//        while ((len = bufferedInputSteam.read(stream)) > 0) {
//            rasrRequestSample.start(stream);
//            Thread.sleep(125);
//        }
        List<byte[]> list = ByteUtils.subToSmallBytes(new File(audio_data), subLength);
        for (int i = 0; i < list.size(); i++) {
            rasrRequestSample.start(list.get(i));
//        sleepSomeTime(125); // 对于8K的语音,每秒发出2048*8 = 16KB数据,与实际相符。
        }
//    rasrRequestSample.start();
        sleepSomeTime(600000); // 10分钟后停止示例程序。
        rasrRequestSample.stop();
        System.exit(0);
    }
    /**
     * 根据需求启动多个任务,每个任务都独立运行,互不干扰。
     */
    public void start(byte[] contentSteam) {
        for (int i = 1; i <= this.threadNumber; i++) {
            this.taskList.add(voiceTask);
            voiceTask.start(contentSteam);
            sleepSomeTime(20);
        }
    }
    /**
     * 停止全部任务。
     */
    public void stop() {
        voiceTask.stop();
    }
    /**
     * 初始化基础参数, 请将下面的参数值配置成你自己的值。
     * <p>
     * 参数获取方法可参考: <a href="https://cloud.tencent.com/document/product/441/6203">签名鉴权 获取签名所需信息</a>
     */
    private static void initBaseParameters() {
        // Required
        AsrBaseConfig.appId = "";
        AsrBaseConfig.secretKey = "";
        AsrBaseConfig.secretId = "";
        // optional,根据自身需求配置值
        AsrInternalConfig.setSdkRole(SdkRole.VAD); // VAD版用户请务必赋值为 SdkRole.VAD
        AsrPersonalConfig.responseEncode = ResponseEncode.UTF_8;
        AsrPersonalConfig.engineModelType = "8k_0";
        AsrPersonalConfig.voiceFormat = VoiceFormat.wav;
        // optional, 可忽略
        AsrGlobelConfig.CUT_LENGTH = 4096; // 每次发往服务端的语音分片的字节长度,8K语音建议设为4096,16K语音建议设为8192。
        // AsrGlobelConfig.NEED_VAD = 0; // 是否要做VAD,默认为1,表示要做。线上用户不适用,请忽略。
        AsrGlobelConfig.NOTIFY_ALL_RESPONSE = true; // 是否回调每个分片的回复。如只需最后的结果,可设为false。
        // AsrBaseConfig.PRINT_CUT_REQUEST = true; // 打印每个分片的请求,用于测试。
        AsrBaseConfig.PRINT_CUT_RESPONSE = true; // 打印中间结果,用于测试,生产环境建议设为false。
        // 默认使用自定义连接池,连接数可在AsrGlobelConfig中修改,更多细节参数,可直接修改源码HttpPoolingManager.java,然后自行打Jar包。
        // AsrGlobelConfig.USE_CUSTOM_CONNECTION_POOL = true;
    }
    private static void sleepSomeTime(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            // ignore
        }
    }
    /**
     * 生成可执行Jar后,运行Jar时传入参数的简单处理。不建议这样子传参数。
     * <p>
     * 比如这个命令传入了4个参数: java -jar realAsrSdk_run.jar 10 test_wav/8k/8k_19s.wav 8k false
     * <p>
     * 详情可见:out_runnable_jar/command_reference.txt
     */
    private void setArguments(String[] args) {
//        if (args.length > 0)
//            this.threadNumber = Integer.parseInt(args[0]); // 使用传入的参数赋值线程个数
//        if (args.length > 1) {
            this.voiceFile = args[1];
            this.checkSetVoiceFormat(this.voiceFile);
//        }
//        if (args.length > 2) {
//            AsrPersonalConfig.engineModelType = args[2];
//            if (AsrPersonalConfig.engineModelType == "16k_0")
//                AsrGlobelConfig.CUT_LENGTH = 8192; // 16K语音 也设置成每秒发4次请求,优化演示效果。
//        }
//        if (args.length > 3){
//            AsrGlobelConfig.NOTIFY_ALL_RESPONSE = Boolean.parseBoolean(args[3]);
//        }
//
    }
    private void checkSetVoiceFormat(String voiceFile) {
        int index = voiceFile.lastIndexOf(".");
        if (index == -1){
            return;
        }
        String formatName = voiceFile.substring(index + 1).trim().toLowerCase();
        AsrPersonalConfig.voiceFormat = VoiceFormat.parse(formatName);
    }
}

回调类:

package com.jack.chat.asrtencent.service;// --------------------------------------------------------------------------------------------------------------
import com.tencent.cloud.asr.realtime.sdk.cache_handler.FlowHandler;
import com.tencent.cloud.asr.realtime.sdk.model.response.TimeStat;
import com.tencent.cloud.asr.realtime.sdk.model.response.VadResponse;
import com.tencent.cloud.asr.realtime.sdk.model.response.VadResult;
import com.tencent.cloud.asr.realtime.sdk.model.response.VoiceResponse;
import com.tencent.cloud.asr.realtime.sdk.utils.JacksonUtil;
import com.jack.chat.asr.model.AsrResultModel;
import com.jack.chat.fs.service.FsService;
import com.jack.chat.socket.service.WebSocketMapUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
 * 用户自己写的回调Handler.被NotifyService服务线程(可理解为用户线程B)调用。
 */
public class MyResponseHandler implements FlowHandler {
    private String handlerId;
    private FsService fsService;
    private String tel;
    public AtomicInteger okLineCount = new AtomicInteger(1);
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
    public MyResponseHandler(String handlerId, String tel, FsService fsService) {
        this.handlerId = handlerId;
        this.tel = tel;
        this.fsService = fsService;
    }
    /**
     * 回复数据通过此方法通知到用户。
     */
    @Override
    public void onUpdate(Object... params) {
        VadResponse response = (VadResponse) params[0]; // Vad版用户请用此行代替下面一行
//    VoiceResponse response = (VoiceResponse) params[0];
        // Your own logic.
        System.out.println(sdf.format(new Date()) + " Handler_" + this.handlerId + ", received response -->: "
                + response.getOriginalText());
        System.out.println("所有:" + JacksonUtil.toJsonString(response));
        // 可以查看延迟。
//    this.printDelay(response);
        // 可以提取出当前Vad断句回复。适用于Vad版用户,线上用户请忽略。
        if (response.getResultList() != null) {
            for (VadResult vadResult : response.getResultList()) {
                int lineNo = okLineCount.get();
                String content = vadResult.getVoiceTextStr();
                //判断是否是整句结束
                if (2 == vadResult.getSliceType()) {
                    okLineCount.addAndGet(1);
                }
                System.out.println("Received vad response: " + vadResult.getVoiceTextStr());
                AsrResultModel asrResultModel = new AsrResultModel();
                asrResultModel.setLineNo(lineNo);
                asrResultModel.setResult(content);
                try {
                    if (StringUtils.isNotEmpty(content)) {
                        String telChannel = fsService.getTelChannel(tel);
                        String message = fsService.message(tel, asrResultModel);
                        System.out.println("telChannel:" + telChannel + "message" + message);
                        WebSocketMapUtil.getUserWs(telChannel).sendMessage(message);
                    }
                } catch (Exception e) {
                    System.out.println("tencent发送消息失败:" + e.getMessage());
                }
            }
        }
    }
    /**
     * 查看和打印延迟信息。延迟统计方法可从项目docs目录中查看,或浏览下面的含义解释。
     *
     * <pre>
     * 实例如下:
     * <<<End_Cut>>> write delay: 103 ms, node delay: 103 ms, notify delay: 105 ms. Pre average write: 101 ms, node: 102 ms.
     * 分别表示:发送延迟、节点延迟、通知延迟。前面N个分片的平均发送、平均节点延迟。
     *
     * 如需测试语音发完后多久能收完全部识别结果,可从:“<<<End_Cut>>>” 中的notify delay获得参考。建议以write Delay作为服务性能考量。
     *
     * 延迟含义解释:
     * WriteDelay:    数据收发和网络延迟+解析Delay(1-2ms)。
     * NodeDelay:      数据滞留延迟 + WriteDelay。   即:从客户add完成1个分片数据开始,至分片结果收到为止,期间总的时间消耗。
     * NotifyDelay: NodeDelay + 客户onHander Delay(处理回复耗时)。此值若大于NodeDelay且在增长,会导致Response堆积,最终内存溢出。
     * </pre>
     */
    private void printDelay(VoiceResponse voiceResponse) {
        TimeStat timeStat = voiceResponse.getTimeStat();
        if (voiceResponse.isEndCut()) {
            this.printDelay("<<<End_Cut>>>", timeStat);
        } else {
            this.printDelay("<<<Middle_Cut>>>", timeStat);
        }
    }
    private void printDelay(String cutType, TimeStat timeStat) {
        System.out.println(sdf.format(new Date()) + " " + cutType + " write delay: " + timeStat.getWriteDelay()
                + " ms, node delay: " + timeStat.getNodeDelay() + " ms, notify delay: " + timeStat.getNotifyDelay()
                + " ms. Pre average write: " + timeStat.getPreAverageWriteDelay() + " ms, node: "
                + timeStat.getPreAverageNodeDelay() + " ms.");
    }
}

调用类:

     System.out.println("使用腾讯");
                String s = RandomUtils.generateNumber(9);
                rasrAsynRequestSample = new RasrAsynRequestSample(s, new VoiceTask(s));
                rasrAsynRequestSample.init(tel);


在建立ws接口成功以后执行上面调用代码,从传输的参数可以知道,我是根据不同的手机号码进行区分回调通道的, 每个回调类中都有一个私有变量tel,用来区分回调通道。

目录
相关文章
|
11月前
|
Java API Maven
商汤人像如何对接?Java代码如何写?
商汤人像如何对接?Java代码如何写?
346 5
|
11月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
519 3
|
11月前
|
JSON 自然语言处理 Java
这款轻量级 Java 表达式引擎,真不错!
AviatorScript 是一个高性能、轻量级的脚本语言,基于 JVM(包括 Android 平台)。它支持数字、字符串、正则表达式、布尔值等基本类型,以及所有 Java 运算符。主要特性包括函数式编程、大整数和高精度运算、完整的脚本语法、丰富的内置函数和自定义函数支持。适用于规则判断、公式计算、动态脚本控制等场景。
|
12月前
|
自然语言处理 安全 Java
Aviator Java 表达式引擎
AviatorScript 是一门高性能、轻量级寄宿于 JVM 之上的脚本语言。
306 10
|
12月前
|
Java 数据处理 开发者
Java Http 接口对接太繁琐?试试 UniHttp 框架~
【10月更文挑战第10天】在企业级项目开发中,HTTP接口对接是一项常见且重要的任务。传统的编程式HTTP客户端(如HttpClient、Okhttp)虽然功能强大,但往往需要编写大量冗长且复杂的代码,这对于项目的可维护性和可读性都是一个挑战。幸运的是,UniHttp框架的出现为这一问题提供了优雅的解决方案。
313 0
|
12月前
|
JSON Java fastjson
Java Http 接口对接太繁琐?试试 UniHttp 框架吧
UniHttp 是一个声明式的 HTTP 接口对接框架,旨在简化第三方 HTTP 接口的调用过程。通过注解配置,开发者可以像调用本地方法一样发起 HTTP 请求,无需关注请求的构建和响应处理细节。框架支持多种请求方式和参数类型,提供灵活的生命周期钩子以满足复杂的对接需求,适用于企业级项目的快速开发和维护。GitHub 地址:[UniAPI](https://github.com/burukeYou/UniAPI)。
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
463 11
|
Java 数据库连接 缓存
Hibernate性能调优:五大秘籍,让应用效能飙升,告别慢如蜗牛的加载,体验丝滑般流畅!
【8月更文挑战第31天】本文深入探讨了提升Hibernate应用性能的五大技巧,包括选择合适的缓存策略、优化查询语句、合理使用Eager与Lazy加载、批量操作与事务管理以及利用索引和数据库优化。通过正确配置多级缓存、分页查询、延迟加载、批量处理及合理创建索引,能够显著提高应用响应速度与吞吐量,改善用户体验。这些技巧需根据具体应用场景灵活调整,以实现最佳性能优化效果。
496 0
|
Java API Spring
打造未来电商新引擎:揭秘Java可扩展API设计,让支付与物流灵活如丝,引领电商时代潮流!
【8月更文挑战第30天】本文通过电商平台案例,探讨了如何设计可扩展的Java API。首先定义支付和物流服务的接口与抽象类,然后实现具体服务,接着引入工厂模式或依赖注入管理服务实例,最后通过配置实现灵活扩展。这种设计确保了应用架构的灵活性和长期稳定性。
162 3
|
存储 机器学习/深度学习 人工智能
人工智能平台PAI使用问题之特征平台是否可以与Java进行对接
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。