【!最终呈现方式为jar包直接运行,实现原理等可供参考】

运行图

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓以下是正文↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

1.注册百度开发者

(1)语音合成的方式有很多,为了简洁,我们使用第三方语音合成API,这里选择百度语音。详细注册流程官方文档很详细,这里不做过多介绍。传送门,我们需要的是AppID,API Key和Secret Key 如下图

(2)我们要做java后台处理,所以使用java JDK即可,传送门

2使用Idea进行程序的编写

(1)创建普通maven工程即可,相信优秀的你一定都会了,这里不啰嗦了。
(2)引入依赖

       <!-- lombok神器--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!-- 百度API --><dependency><groupId>com.baidu.aip</groupId><artifactId>java-sdk</artifactId><version>4.11.3</version></dependency>

(3)创建百度语音合成工具类
ConstansHelper.java

import com.baidu.aip.speech.AipSpeech;
import com.baidu.aip.speech.TtsResponse;
import com.baidu.aip.util.Util;
import lombok.Data;
import org.json.JSONObject;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/*** @Desc:* @Author: wangyafei* @Date: 2019/9/5 18:04* @Version 1.0*/
@Data
public class ConstansHelper {//设置APPID/AK/SK 注册百度开发者会生成public static final String APP_ID = "APP_ID ";public static final String API_KEY = "API_KEY ";public static final String SECRET_KEY = "SECRET_KEY ";/*** @param spd 语速,取值0-15,默认为5中语速* @param pit 音调,取值0-15,默认为5中语调* @param vol 音量,取值0-15,默认为5中音量* @param per 发音人选择, 0为女声,1为男声,*            3为情感合成-度逍遥,*            4为情感合成-度丫丫,默认为普通女* @param txt 要转换的文本*/public static String makeSpeech(String spd, String pit, String vol, String per, String txt) {// 初始化一个AipSpeechAipSpeech client = new AipSpeech(APP_ID, API_KEY, SECRET_KEY);// 可选:设置网络连接参数client.setConnectionTimeoutInMillis(2000);client.setSocketTimeoutInMillis(60000);// 设置可选参数HashMap<String, Object> options = new HashMap<String, Object>();if (!"请选择".equals(spd)) {options.put("spd", spd);}if (!"请选择".equals(pit)) {options.put("pit", pit);}if (!"请选择".equals(vol)) {options.put("vol", vol);}if (!"请选择".equals(per)) {switch (per){case "女声":options.put("per", 0);break;case "男声":options.put("per", 1);break;case "情感合成-度逍遥":options.put("per", 3);break;case "情感合成-度丫丫":options.put("per", 4);break;}}SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");String dirName = sdf.format(new Date());isChartPathExist("D:\\音频合成\\" + dirName);// 调用接口//合成文本长度必须小于1024字节,如果本文长度较长,可以采用多次请求的方式。文本长度不可超过限制List<String> txtList = splitFunction(txt, 1024);byte[] all =null;for (String s : txtList) {TtsResponse res = client.synthesis(s, "zh", 1, options);byte[] data = res.getData();if(data != null){all = byteMerger(all,data);}}//存储位置,自己决定放到哪里,我放到了D盘String fileName  ="D:\\音频合成\\" + dirName + "\\" + (txt.length()>15?txt.substring(0, 15):txt) + "-"+System.currentTimeMillis() + "output.mp3";if (all != null) {try {Util.writeBytesToFileSystem(all, fileName);} catch (IOException e) {e.printStackTrace();}}File file = new File(fileName);return fileName;}/*** 文件夹磁盘路径 文件夹不存在创建文件夹* @param dirPath*/private static void isChartPathExist(String dirPath) {File file = new File(dirPath);if (!file.exists()) {file.mkdirs();}}/*** 根据字节长度进行切割* 中文在不同编码中占用的字节数是不同的,GBK编码中,一个汉字占两个字节,UTF-8编码格式中,一个汉字占3个字节* @param src* @param bytes* @return*/public static List<String> splitFunction(String src, int bytes){try {if(src == null){return null;}List<String> splitList = new ArrayList<String>();int startIndex = 0;    //字符串截取起始位置int endIndex = bytes > src.length() ? src.length() : bytes;  //字符串截取结束位置while(startIndex < src.length()){String subString = src.substring(startIndex,endIndex);//截取的字符串的字节长度大于需要截取的长度时,说明包含中文字符//在GBK编码中,一个中文字符占2个字节,UTF-8编码格式,一个中文字符占3个字节。while (subString.getBytes("GBK").length > bytes) {--endIndex;subString = src.substring(startIndex,endIndex);}splitList.add(src.substring(startIndex,endIndex));startIndex = endIndex;//判断结束位置时要与字符串长度比较(src.length()),之前与字符串的bytes长度比较了,导致越界异常。endIndex = (startIndex + bytes) > src.length() ?src.length()  : startIndex+bytes ;}return splitList;} catch (Exception e) {e.printStackTrace();}return null;}/*** 合并两个byte数组* @param byte_1* @param byte_2* @return*/public static byte[] byteMerger(byte[] byte_1, byte[] byte_2){if(byte_1 == null){return byte_2;}byte[] byte_3 = new byte[byte_1.length+byte_2.length];System.arraycopy(byte_1, 0, byte_3, 0, byte_1.length);System.arraycopy(byte_2, 0, byte_3, byte_1.length, byte_2.length);return byte_3;}
}

(4)创建GUI文件
网上大多数是,直接创建一个Test.form页面的教程, 感觉也不是很方便,这里采用直接写代码的方式。
Container.java


import org.springframework.util.StringUtils;
import org.wyf.yuyindemo.utils.ConstansHelper;import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;/*** @Desc:* @Author: wangyafei* @Date: 2019/9/6 10:47* @Version 1.0*/
public class Container extends Thread implements ActionListener, WindowListener {private static int totalTime = 40;private static float totalDiff = 0.0f;private TextField txt;private TextArea taLog;         //日志输出区域 不可以设置颜色相关private JButton jbtStart,jbtReset;       //开始按钮;重置按钮private JComboBox spd,pit,vol,per;//语速,语调。音量,角色private JLabel tips;@Overridepublic void run() {//画页面//父窗体JFrame jFrame = new JFrame("语音生成小工具");// 创建按钮jbtStart = new JButton("生成");jbtReset = new JButton("重置");jbtStart.addActionListener(this);jbtReset.addActionListener(this);// 创建相关的文本域txt = new TextField("我是文本");spd = new JComboBox();pit = new JComboBox();vol = new JComboBox();per = new JComboBox();spd.addItem("请选择");pit.addItem("请选择");vol.addItem("请选择");for (int i = 0; i <15 ; i++) {spd.addItem(i);pit.addItem(i);vol.addItem(i);}per.addItem("请选择");per.addItem("女声");per.addItem("男声");per.addItem("情感合成-度逍遥");per.addItem("情感合成-度丫丫");JLabel jb1 = new JLabel("   语速");JLabel jb2 = new JLabel("   语调");JLabel jb3 = new JLabel("   音量");JLabel jb4 = new JLabel("   角色");JPanel sel = new JPanel(new GridLayout(4,2));sel.add(jb1);sel.add(spd);sel.add(jb2);sel.add(pit);sel.add(jb3);sel.add(vol);sel.add(jb4);sel.add(per);taLog = new TextArea();taLog.setColumns(30);taLog.setRows(150);taLog.setBackground(Color.CYAN);taLog.setFont(new Font("宋体",Font.BOLD,16));taLog.setEditable(false);// 创建相关的Label标签JLabel labelStart = new JLabel("请输入文本:");JLabel labelTip1 = new JLabel("<html>仅供测试<br>如有问题请联系<br>QQ772173722</html>");//提示输入文本JPanel inputTxt = new JPanel(new GridLayout(2, 1));inputTxt.add(labelStart,BorderLayout.CENTER);inputTxt.add(txt,BorderLayout.CENTER);//开始按钮及左右信息JPanel panel4 = new JPanel(new GridLayout(1, 3));panel4.add(labelTip1);panel4.add(jbtStart);panel4.add(jbtReset);JPanel log = new JPanel(new GridLayout(1,1));tips = new JLabel();log.add(tips);//上级布局JPanel panel22 = new JPanel(new GridLayout(4,1));panel22.add(sel);panel22.add(inputTxt);panel22.add(panel4);panel22.add(tips);jFrame.setLayout(new BorderLayout());jFrame.add(panel22, BorderLayout.CENTER);// 初始化JFrame窗口jFrame.setLocation(800, 300);jFrame.setSize(600, 500);jFrame.setBackground(Color.darkGray);jFrame.setResizable(true);jFrame.setVisible(true);}/*** 点击监听器* @param view*/@Overridepublic void actionPerformed(ActionEvent view) {if (view.getSource() == jbtStart) {String spdStr =spd.getSelectedItem().toString();String pitStr = pit.getSelectedItem().toString();String volStr = vol.getSelectedItem().toString();String perStr = per.getSelectedItem().toString();String txtStr =txt.getText() ;if (!StringUtils.isEmpty(spdStr) && !StringUtils.isEmpty(pitStr) && !StringUtils.isEmpty(volStr) && !StringUtils.isEmpty(perStr) && !StringUtils.isEmpty(txtStr)) {makeSpeech(spdStr,pitStr,volStr,perStr,txtStr);}}else if(view.getSource() == jbtReset){//重置组件内容tips.setText(null);txt.setText("我是文本");spd.setSelectedIndex(0);per.setSelectedIndex(0);pit.setSelectedIndex(0);vol.setSelectedIndex(0);}}/*** 合成语音* @param spdStr* @param pitStr* @param volStr* @param perStr* @param txtStr*/private void makeSpeech(String spdStr, String pitStr, String volStr, String perStr, String txtStr) {String fileName = ConstansHelper.makeSpeech(spdStr, pitStr, volStr, perStr, txtStr);if(!StringUtils.isEmpty(fileName)){//返回值 ,0=是,1=否,2=取消int dialog = JOptionPane.showConfirmDialog(null, "合成成功!是否打开文件所在位置?");tips.setText("文件位置: "+fileName);if(dialog == 0) {try {String open = fileName.substring(0, fileName.lastIndexOf("\\"));//打开文件所在位置Runtime.getRuntime().exec("explorer.exe " + open);} catch (IOException e) {e.printStackTrace();}}}}@Overridepublic void windowOpened(WindowEvent e) {}@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}@Overridepublic void windowClosed(WindowEvent e) {System.exit(0);}@Overridepublic void windowIconified(WindowEvent e) {}@Overridepublic void windowDeiconified(WindowEvent e) {}@Overridepublic void windowActivated(WindowEvent e) {}@Overridepublic void windowDeactivated(WindowEvent e) {}public static void main(String[] args) {Container container = new Container();container.run();}
}

3.生成Jar包

(1)默认情况下项目设置project structure(快捷键ctrl+alt+shift+S)里是没有artifacts的,我们新增一个

(2)选择main方法所在的类

注:如果出现"点击jar包没有反应,没有清单文件主函数"的问题,修改目录到src下即可
修改前:
修改后:
(3)此时build一下就可以啦

利用百度API实现语音合成相关推荐

  1. 利用百度API查询手机号归属地

    利用百度Api查询手机号归属地 先到百度API官网查看其有关说明,这是其官网:http://apistore.baidu.com/ 可在此页面找到相关说明. 打开网址可以看到好几个号码归属地的查询,有 ...

  2. 将手绘地图或自制地图显示在网页上(利用百度API)

    利用百度APi实现将手绘地图展示在网页上,达到类似这样的效果: 切图参考了:cnblog jz1108 并用了其工具, 表示非常感谢! 百度地图API目前默认支持两种地图类型(map type):普通 ...

  3. 爬取去哪儿网酒店信息,再利用百度API将酒店地址的经纬度爬取!

    Python3 的 selenium库可以模拟打开页面,获得加载完成的页面信息,一些基本用法,请自行度娘,就不再赘述了 1.将某城市的所有酒店链接爬取下来. 先打开两个酒店页面 ** https:// ...

  4. 利用百度API Store接口进行火车票查询

    火车票查询 项目源码下载链接: Github:https://github.com/VincentWYJ/TrainTicketQuery 博客文件:http://files.cnblogs.com/ ...

  5. php调用百度接口获取经纬度,利用百度API(js),通过地址获取经纬度的注意事项...

    网上给的很多答案都是这种: http://api.map.baidu.com/geocoder?address=地址&output=输出格式类型&key=用户密钥&city=城 ...

  6. 微信小程序利用百度api达成植物识别

    看完本文你可学会: 如何使用百度智能云 如何在微信小程序中去接入百度api,达成植物识别的效果 如何使用百度智能云? 官网:https://cloud.baidu.com 进入官网,在用户中心下选择图 ...

  7. PHP学习笔记:利用百度api实现手机归属地查询

    从来没有用过api,都不知道怎么获得api的数据,跟着demo,然后修改,终于实现了手机号码查询的功能,代码和说明很全,大家试试. <?php /*** Created by jianqingw ...

  8. 利用百度API实现文字识别

    简介 将图片上文字识别出来,是一件非常有意思的事,而这样技术的实现,同样有助于我们实现图片验证码的识别,将图像翻译成文字一般成为光学文字识别(Optical Character Recognition ...

  9. 利用百度API写出自己的桌面翻译器

    下面三个是我参考到的博主的博文,大家有兴趣也可以去了解一下,我在他们的基础上加入了我自己的一些想法,程序也做得更合我心意.感谢这几位博主. GUI使用教程 翻译程序的博文 GUI以及封装博文 前期准备 ...

最新文章

  1. nginx resolver 指令的使用
  2. 机器视觉关键技术之图像增强技术
  3. vector 容器 动态数组总结
  4. 独家 | 一文读懂人工神经网络学习原理
  5. 扇贝编程python是干嘛的-产品观察 | 以对话式互动学习撬动转化,扇贝编程瞄准职教市场...
  6. 通过jS打包下载图片
  7. java poi 导出excel 数字有问题
  8. 王道操作系统考研笔记——1.1.1 操作系统的概念、功能和目标
  9. CSDN博客如何在有序序列中缩进代码段或图片
  10. [cogs1065]绿豆蛙的归宿
  11. 宇宙最全的架构开发技术百科全书
  12. MySQL 创建主外键
  13. avalon做的抽奖效果
  14. opengl入门(ubuntu版)(一)
  15. 下载win7原版ios系统文件
  16. Java数字转化为阿拉伯数字_Java实现中文数字转换为阿拉伯数字
  17. ShareTech大企业邮件服务器系统软件
  18. JAVA 实现《坦克大战联机版》游戏
  19. PHPUnit 在 Windows下的安装
  20. mycat 实现读写分离

热门文章

  1. python爬取知乎文章_大佬分享Python编程实现爬取知乎用户信息的例子
  2. QT实现有纹理和照明的简单立方体
  3. Window10手把手带你YOLOV5的火焰烟雾检测+tensorrt量化加速+C++动态库打包
  4. Linux惊群效应之Nginx解决方案
  5. java指定日期的季度以及季度第一天和最后一天(季度统计报表)
  6. org.apache.ibatis.binding.BindingException:( Mapper method has an unsupported return type)
  7. 实战:150行Go实现高性能socks5代理
  8. 【Matlab风电功率预测】粒子群算法优化BP神经网络风电功率预测【含源码 347期】
  9. javascript脚本语言电子书大全免费下载
  10. WPF中如何将List<string>数据绑定到DataGrid控件中