用java做一套离线且免费的智能语音系统,ASR+LLM+TTS

其实调用第三方接口完成一个智能语音系统是非常简单的,像阿里、科大讯飞、微软都有相关接口,直接根据官方文档集成就可以,但想要离线的就要麻烦一点了,主要是想不花钱,现在人工智能基本是python的天下,不得不感慨,再不学python感觉自己要被淘汰了。

言归正传,首先说一下标题中的ASR+LLM+TTS,ASR就是语音识别,LLM就是大语言模型,TTS就是文字转语音,要想把这几个功能做好对电脑性能要求还是蛮高的,本次方案是一个新的尝试也是减少对性能的消耗

1.先看效果

 生成的音频效果放百度网盘 通过网盘分享的文件:result.wav 链接: pan.baidu.com/s/19ImtqunH… 提取码: hm67 听完之后是不是感觉效果很好,但是。。。后面再说吧

2.如何做

2.1ASR功能

添加依赖

 

xml

代码解读

复制代码

<!-- 获取音频信息 --> <dependency> <groupId>org</groupId> <artifactId>jaudiotagger</artifactId> <version>2.0.3</version> </dependency> <!-- 语音识别 --> <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>5.7.0</version> </dependency> <dependency> <groupId>com.alphacephei</groupId> <artifactId>vosk</artifactId> <version>0.3.32</version> </dependency>

代码实现,需要提前下载模型,去vosk官网下载:VOSK Models (alphacephei.com)中文模型一个大的一个小的,小的识别速度快准确率低,大的识别速度慢准确率高


提前预加载模型,提升识别速度

整理了一份好像面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题

需要全套面试笔记【点击此处即可】免费获取

java

代码解读

复制代码

private static final Model model = loadModel(); private static Model loadModel() { try { String path=System.getProperty("user.dir"); return new Model(path+"\vosk-model-small-cn-0.22"); } catch (Exception e) { throw new RuntimeException("Failed to load model", e); } }

语音转文字方法实现

 

ini

代码解读

复制代码

public String voiceToText(String filePath) { File file = new File(filePath); LibVosk.setLogLevel(LogLevel.DEBUG); String msg = null; int sampleRate = 0; RandomAccessFile rdf = null; /** * "r": 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 * "rw": 打开以便读取和写入。 * "rws": 打开以便读取和写入。相对于 "rw","rws" 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。 * "rwd" : 打开以便读取和写入,相对于 "rw","rwd" 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。 */ try { rdf = new RandomAccessFile(file, "r"); sampleRate=toInt(read(rdf)); System.out.println(file.getName() + " SampleRate:" + sampleRate); // 采样率、音频采样级别 8000 = 8KHz rdf.close(); } catch (FileNotFoundException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } try ( InputStream ais = AudioSystem.getAudioInputStream(file); Recognizer recognizer = new Recognizer(model, 16000)) { int bytes; byte[] b = new byte[1024]; while ((bytes = ais.read(b)) >= 0) { recognizer.acceptWaveForm(b, bytes); } String result=recognizer.getResult(); JSONObject jsonObject = JSONObject.parseObject(result); msg=jsonObject.getString("text"); } catch (UnsupportedAudioFileException e) { throw new RuntimeException(e); } catch (IOException e) { throw new RuntimeException(e); } return msg; }

2.2LLM问答功能

这个就要请出神奇的羊驼ollama(链接:Ollama),下载即用非常简单,可以运行大部分主流大语言模型,在官网models选择要加载的模型在控制台运行对应的命令即可

 添加依赖

 

xml

代码解读

复制代码

<dependency> <groupId>io.springboot.ai</groupId> <artifactId>spring-ai-ollama-spring-boot-starter</artifactId> <version>1.0.3</version> </dependency>

加入配置

 

yaml

代码解读

复制代码

spring: ai: ollama: base-url: http://10.3.0.178:11434 //接口地址 默认端口11434 chat: options: model: qwen2 //模型名称 enabled: true

代码实现,引入OllamaChatClient,然后调用call方法

 

ini

代码解读

复制代码

@Resource private OllamaChatClient ollamaChatClient; //msg为提问的信息 String ask=ollamaChatClient.call(msg);

2.3TTS功能

添加依赖

 

xml

代码解读

复制代码

<dependency> <groupId>com.hynnet</groupId> <artifactId>jacob</artifactId> <version>1.18</version> </dependency>

代码实现

 

java

代码解读

复制代码

public boolean localTextToSpeech(String text, int volume, int speed,String outPath) { try { // 调用dll朗读方法 ActiveXComponent ax = new ActiveXComponent("Sapi.SpVoice"); // 音量 0 - 100 ax.setProperty("Volume", new Variant(volume)); // 语音朗读速度 -10 到 +10 ax.setProperty("Rate", new Variant(speed)); // 输入的语言内容 Dispatch dispatch = ax.getObject(); // 本地执行朗读 // Dispatch.call(dispatch, "Speak", new Variant(text)); //开始生成语音文件,构建文件流 ax = new ActiveXComponent("Sapi.SpFileStream"); Dispatch sfFileStream = ax.getObject(); //设置文件生成格式 ax = new ActiveXComponent("Sapi.SpAudioFormat"); Dispatch fileFormat = ax.getObject(); // 设置音频流格式 Dispatch.put(fileFormat, "Type", new Variant(22)); // 设置文件输出流格式 Dispatch.putRef(sfFileStream, "Format", fileFormat); // 调用输出文件流打开方法,创建一个音频文件 Dispatch.call(sfFileStream, "Open", new Variant(outPath), new Variant(3), new Variant(true)); // 设置声音对应输出流为输出文件对象 Dispatch.putRef(dispatch, "AudioOutputStream", sfFileStream); // 设置音量 Dispatch.put(dispatch, "Volume", new Variant(volume)); // 设置速度 Dispatch.put(dispatch, "Rate", new Variant(speed)); // 执行朗读 Dispatch.call(dispatch, "Speak", new Variant(text)); // 关闭输出文件 Dispatch.call(sfFileStream, "Close"); Dispatch.putRef(dispatch, "AudioOutputStream", null); // 关闭资源 sfFileStream.safeRelease(); fileFormat.safeRelease(); // 关闭朗读的操作 dispatch.safeRelease(); ax.safeRelease(); return true; } catch (Exception e) { e.printStackTrace(); return false; } }

到此为止功能就全部实现了,在不联网的情况下也可以免费使用,但这个TTS生成出来的语音太机器了,所以在上面的示例中我说但是,因为机器音实在太难受了,所以用了另一个方案,但这个方案需要联网,暂时看是不需要收费 ,这个大家就看原作者介绍吧(ikfly/java-tts: java-tts 文本转语音 (github.com)

最终实现效果来看还是能接受的吧,整个过程速度还比较快,python的语音相关项目也看了很多,如果部署一个python的TTS服务,效果可能还会好点,但是我试过的速度都有点慢啊,还是容我再继续研究一下吧

  • 15
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值