1.实现效果如下:
输入文字(支持中英文),点击转换生成***.wav文件,点击下载到本地就可。
生成后的音频文件播放,时长1分8秒
2.实现代码:
这次采用jacob实现,相比百度AI需要联网,本项目定位内网环境实现。所以最终采jacob。
1.环境配置:
本次采用版本jacob-1.19,我们需要下载jacob.jar和dll
下载地址:jacob语音生成文件,jacobx64.dll和jacob.jar为1.9-Java文档类资源-CSDN下载
官网地址:JACOB - Java COM Bridge download | SourceForge.net
下载后得到两个文件:
jacob.dll:配置到jdk环境中
jacob.jar:放入到项目中并配置下pox和Idea 的dependencies下
第一步:
jacob.dll放入:C:\Program Files\Java\jdk1.8.0_121\jre\bin
第二步:
1.首先有一个spring boot项目,没有就搭建一个
2.把jacob放到项目resources>lib目录下
3.在pom.xml文件添加依赖:
<!--添加本地的jacob.jar包-->
<dependency>
<groupId>com.jacob</groupId>
<artifactId>jacob</artifactId>
<version>1.19</version>
<!--system使用本地jar包-->
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/jacob.jar</systemPath>
</dependency>
4.在idea下的项目中添加依赖包,
5.这样环境就搭建完成。
2.编码:
核心代码,这样就可以输入文字,生成音频文件保存到本地目录中,然后下载音频文件就只需要读取文件就可以。
//输入文本内容,生成文件地址 text为输入的文本信息
public void audioFile(String text){
try {
//jacob.dll没成功安装,执行这一步会出错
//构建音频格式 调用注册表应用
Dispatch spAudioFormat = new ActiveXComponent("Sapi.SpAudioFormat").getObject();
//音频文件输出流
Dispatch spFileStream = new ActiveXComponent("Sapi.SpFileStream").getObject();
//构建音频对象
Dispatch spVoice = new ActiveXComponent("Sapi.SpVoice").getObject();
//设置spAudioFormat音频流格式类型22
Dispatch.put(spAudioFormat, "Type", new Variant(22));
//设置spFileStream文件输出流的音频格式
Dispatch.putRef(spFileStream, "Format", spAudioFormat);
//设置spFileStream文件输出流参数地址等
Dispatch.call(spFileStream, "Open", new Variant("D:\speech\48641486.wav"), new Variant(3), new Variant(true));
//设置spVoice声音对象的音频输出流为输出文件对象
Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
//设置spVoice声音对象的音量大小100
Dispatch.put(spVoice, "Volume", new Variant(100));
//设置spVoice声音对象的速度 0为正常速度,范围【..-2 -1 0 1 2..】
Dispatch.put(spVoice, "Rate", new Variant(0));
//设置spVoice声音对象中的文本内容
Dispatch.call(spVoice, "Speak", new Variant(text));
//关闭spFileStream输出文件
Dispatch.call(spFileStream, "Close");
//释放资源
spVoice.safeRelease();
spAudioFormat.safeRelease();
spFileStream.safeRelease();
}catch (Exception e){
System.out.println(e.getMessage());
}
}
3.其他业务代码:非核心
下面就贴上完整的项目代码和配置文件
1.项目结构:
主要就几个文件:HomeController、TextToSpeechFileService、index.html、pom.xml
2.pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>text_speech</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>text_speech</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.5.0</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--添加本地的jacob.jar包-->
<dependency>
<groupId>com.jacob</groupId>
<artifactId>jacob</artifactId>
<version>1.19</version>
<!--system使用本地jar包-->
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/jacob.jar</systemPath>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.5.0</version>
<configuration>
<mainClass>com.example.text_speech.TextSpeechApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.index.xml
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>文字转语音</title>
<link rel="shortcut icon" href="https://pic.onlinewebfonts.com/svg/img_196224.png">
<link th:href="@{/plugins/layui/src/css/layui.css}" type="text/css" rel="stylesheet"/>
<script th:inline="javascript">
let ctx = /*[[@{/}]]*/ '';
</script>
</head>
<body>
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 80px;">
<legend>文字转音频文件</legend>
</fieldset>
<div class="layui-bg-gray" style="padding: 30px;">
<div class="layui-row layui-col-space15">
<div class="layui-col-md6">
<!--一行内容块-->
<div class="layui-form-item layui-form-text layui-panel" >
<textarea placeholder="请输入内容,支持中英文字。" id="textContent" class="layui-textarea" style="height: 400px"></textarea>
</div>
</div>
<div class="layui-col-md6 ">
<div class="layui-form-item "style="width: 100px">
<button style="margin-top: 100px;" class="layui-btn" onclick="getAudioFile()" >生成音频文件</button>
</div>
<div class="layui-panel" style="width: 400px;margin-left: 200px;top: -50px;height: 200px" >
<div id="noFile" style="margin: 20px">
等待生成文件。
</div>
<div id="existFile" hidden>
<h3 style="text-align: center">音频文件已经生成</h3>
<div style="margin: 20px" >
<div>文件名称:<span id="fileName"></span></div>
<div>文件格式:<span id="fileFormat"></span></div>
<div>创建时间:<span id="fileDate"></span></div>
</div>
<button style="margin: 20px;margin-left: 35%" class="layui-btn" onclick="downFile()">下载文件</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script th:src="@{/plugins/jquery/jquery-1.12.0.min.js}" type="text/javascript"></script>
<script th:src="@{/plugins/layui/src/layui.js}" type="text/javascript"></script>
<script type="text/javascript">
/*文字转换*/
function getAudioFile(){
let loading = layer.load('Loading...', {
shade: [0]
});
let text = $("#textContent").val();
$.post("./tts",{"textContent":text},function (data) {
layer.close(loading);
if (data.code==="1"){
$("#existFile").show();
$("#noFile").hide();
$("#fileName").html(data.name);
$("#fileFormat").html(data.format);
$("#fileDate").html(data.date);
}else {
$("#existFile").hide();
$("#noFile").show();
$("#noFile").html("文件生成发生错误。请检查输入内容。保证只有标准的标点符号和文字。");
}
})
}
/*下载文件*/
function downFile(){
window.open("./downFile?fileName="+$("#fileName").html(), "_blank");
}
</script>
</html>
3.HomeController
package com.example.text_speech.controller;
import com.example.text_speech.service.TextSpeechService;
import com.example.text_speech.service.TextToSpeechFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
@Controller
public class HomeController {
@Autowired
private TextToSpeechFileService textToSpeechFileService;
/***
* @Author: LiaoJJ
* @Description:主页
*/
@RequestMapping({"/index","/",""})
public ModelAndView index(){
return new ModelAndView("index");
}
/***
* @Author: admin
* @Description: 文本转语音
*/
@RequestMapping("/tts")
@ResponseBody
public HashMap<String,String> textTransformAudio(String textContent){
return textToSpeechFileService.audioFile(textContent);
}
/***
* @Author: admin
* @Description: 下载文件
*/
@RequestMapping("/downFile")
@ResponseBody
public void down(String fileName, HttpServletResponse response){
textToSpeechFileService.down(fileName,response);
}
}
4.TextToSpeechFileService
package com.example.text_speech.service;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
/***
* @Author: LiaoJJ
* @Date: 2022/10/12
* @Description:文字转语音文件
*/
@Service
@ComponentScan
public class TextToSpeechFileService {
//语音文件生成的临时文件
@Value("${filePath}")
private String path;
//输入文本内容,生成文件地址
public HashMap<String,String> audioFile(String text){
HashMap<String , String> map = new HashMap<>();
try {
//构建音频格式 调用注册表应用
Dispatch spAudioFormat = new ActiveXComponent("Sapi.SpAudioFormat").getObject();
//音频文件输出流
Dispatch spFileStream = new ActiveXComponent("Sapi.SpFileStream").getObject();
//构建音频对象
Dispatch spVoice = new ActiveXComponent("Sapi.SpVoice").getObject();
//设置spAudioFormat音频流格式类型22
Dispatch.put(spAudioFormat, "Type", new Variant(22));
//设置spFileStream文件输出流的音频格式
Dispatch.putRef(spFileStream, "Format", spAudioFormat);
//随机uuid
String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
String filePath = path + uuid + ".wav";
//设置spFileStream文件输出流参数地址等
Dispatch.call(spFileStream, "Open", new Variant(filePath), new Variant(3), new Variant(true));
//设置spVoice声音对象的音频输出流为输出文件对象
Dispatch.putRef(spVoice, "AudioOutputStream", spFileStream);
//设置spVoice声音对象的音量大小100
Dispatch.put(spVoice, "Volume", new Variant(100));
//设置spVoice声音对象的速度 0为正常速度,范围【..-2 -1 0 1 2..】
Dispatch.put(spVoice, "Rate", new Variant(0));
//设置spVoice声音对象中的文本内容
Dispatch.call(spVoice, "Speak", new Variant(text));
//关闭spFileStream输出文件
Dispatch.call(spFileStream, "Close");
//释放资源
spVoice.safeRelease();
spAudioFormat.safeRelease();
spFileStream.safeRelease();
map.put("code","1");
map.put("name",uuid + ".wav");
map.put("format","wav");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
map.put("date",sdf.format(new Date()));
}catch (Exception e){
System.out.println(e.getMessage());
map.put("code","0");
}
return map;
}
/***
* @Author: LiaoJJ
* @Description: 下载文件
*/
public void down(String fileName, HttpServletResponse response) {
try {
response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream");
//3.设置content-disposition响应头控制浏览器以下载的形式打开文件
response.addHeader("Content-Disposition","attachment;filename=" + new String(fileName.getBytes(),"utf-8"));
//获取文件输入流
InputStream in = new FileInputStream(path+fileName);
int len = 0;
byte[] buffer = new byte[1024];
OutputStream out = response.getOutputStream();
while ((len = in.read(buffer)) > 0) {
//将缓冲区的数据输出到客户端浏览器
out.write(buffer,0,len);
}
in.close();
}catch (Exception e){
e.getMessage();
System.out.println("文件下载失败");
}
}
}
5.application.yml
# 应用名称
spring:
application:
name: text_speech
devtools:
restart:
enabled: true
additional-paths: resources/**,static/**,templates/**
thymeleaf:
prefix: classpath:/templates/
suffix: .html
cache: false # 开启模板缓存
encoding: UTF-8
servlet:
content-type: text/html
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
resources:
add-mappings: true
#静态资源访问路径
static-locations: classpath:/static,classpath:/templates/,file:${config.file.root}
# 应用服务 WEB 访问端口
server:
port: 8080
#配置本地临时文件夹
filePath: D:\speech\
通过上面的几个文件代码,就可以实现文章前面web页面的效果了。
本文章只是一个demo演示。应用到具体业务中还需要做一些修改。
如果其中存在什么问题回复到评论区,及时修改。感谢阅览。