【文本 >>> 语音】⭐️SpringBoot 结合 jacob 简单实现一个文本朗读功能

目录

🍸前言

🍻一、环境准备

🍺二、依赖引入

💞️三、简单启动

🍹四、接口改造

[4.1 封装为一个工具类](#4.1 封装为一个工具类)

[4.2 暴露一个接口](#4.2 暴露一个接口)

[4.3 测试](#4.3 测试)

🌱五、扩展


🍸 前言

小伙伴们大家好,上次分享了一位读者使用国际化上下文 i18n 技术时遇到的兼容问题,也是成功帮他解决了问题,自己同时也学到这种使用方式;这次先放一放常用技术的学习,来看一个小工具,文本转语音,用 java 实现

🍻一、环境准备

一台语音功能没问题的设备(因为要借用机器的语音设备)

本地创建一个可以运行的 SpringBoot 项目,另外准备一个接口模拟工具即可

🍺二、依赖引入

jacob 是一个 Java COM (Component Object Model) 接口库,利用了 COM 接口来调用 Windows 的语音合成(TTS)服务,可以访问 Windows 的 Speech API 或者类似的语音合成工具,用于将文本转换为语音。

在项目的 pom.xml 文件中添加以下依赖,刷新 maven 触发自动下载

XML 复制代码
<dependency>
    <groupId>com.hynnet</groupId>
    <artifactId>jacob</artifactId>
    <version>1.18</version>
</dependency>

注:首次启动的时候可能会遇到如下报错

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jacob-1.18-x64 in java.library.path

只需要手动下载解压后将文件放入到 JDK 的 bin 目录下即可

Release Release 1.18 · freemansoft/jacob-project · GitHub

查看自己 JDK 安装位置的命令如下:

💞️三、简单启动

使用语音功能的主要代码如下:

有四个参数,第一个参数是控制生成的 .mps 多媒体文件的输出位置;

第二个是所需语音阅读的文本内容

第三个第四个是控制语音元素的

java 复制代码
/**
     * 文本转音频
     *
     * @param path   音频生成路径(全路径,带文件名)(例:D:\\aa\\a.mp3)
     * @param text   文本内容
     * @param volume 音量大小 0 - 100
     * @param speed  语音朗读速度 -10 到 +10
     * @return 是否成功
     */
    public static boolean text(String path, String text, int volume, int speed) {
        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(path), 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;
    }

测试下,因为只有本地能听到语音,所以这里就用打印验证方法执行没有出错,结果如下:

🍹四、接口改造

本地测试,该依赖对接设备语音没有问题,在此基础上可以改造为一个接口,该接口的功能就是朗读接口传入的参数,改造后如下:

4.1 封装为一个工具类

这里把保存到本地的代码去掉了,因为只需要阅读即可,不用保留多媒体文件

java 复制代码
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

/**
 * @author HuangBen 
 */
public class SpeakUtil {

    /**
     * 文本转音频
     *
     * @param text   文本内容
     * @return 是否成功
     */
    public static boolean text(String text) {
        try {

            // 调用dll朗读方法
            ActiveXComponent ax = new ActiveXComponent("Sapi.SpVoice");
            // 音量 0 - 100
            ax.setProperty("Volume", new Variant(50));
            // 语音朗读速度 -10 到 +10
            ax.setProperty("Rate", new Variant(0));
            // 输入的语言内容
            Dispatch dispatch = ax.getObject();
            // 本地执行朗读
            Dispatch.call(dispatch, "Speak", new Variant(text));
            
            // 关闭朗读的操作
            dispatch.safeRelease();
            ax.safeRelease();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

}
4.2 暴露一个接口

使用一个 get 请求简单模拟下即可,请求到达之后首先创建一个线程进行语音朗读,主线程进行打印,这是为了防止请求参数过长时,迟迟收不到响应

java 复制代码
    @GetMapping("/testVoice")
    public void testVoice(String word) {
        new Thread(() -> {
            SpeakUtil.text(word);
        }).start();
        System.out.println(word);
    }
4.3 测试

🌱五、扩展

这只是在本地测试使用的方式,实际上隐藏的问题还有很多,比如语音只能在本地机器触发,另外就是如果请求接口参数过长,多个请求同时来的话,可能处理不及时导致部分请求报错或者说无法语音,当然也有一些别的更成熟的依赖可以使用,比如谷歌(需要账号认证),本地只是小耍一下

文章到这里就结束了~

相关推荐
世俗ˊ5 分钟前
微服务-- Sentinel的使用
java·微服务·sentinel
alex180119 分钟前
python实现多个pdf文件合并
java·python·pdf
七禾页话37 分钟前
Java并发常见面试题(上)
java·jvm
Aries2631 小时前
Spring事务传播行为详解
java·数据库·spring
陌上少年,且听这风吟1 小时前
【已解决】SpringBoot3项目整合Druid依赖:Druid监控页面404报错
java·spring boot·spring
code.song1 小时前
电影评论|基于springBoot的电影评论网站设计与实现(附项目源码+论文+数据库)
数据库·spring boot·后端
洗发水很好用1 小时前
新版IDEA提示@Autowired不建议字段注入
java·ide·intellij-idea
model20051 小时前
sahi目标检测java实现
java·算法·目标检测
LG.YDX1 小时前
java:练习
java
给自己做减法2 小时前
排序算法快速记忆
java·算法·排序算法