Java实现智能语音朗读(完整代码+EXE程序制作)

注意

本文主要介绍整个实现过程,一步一步跟着做,相信大家都可以完成的比我好。想要完整代码的可以跳过文章直接去文末获取,如果想要在本机上运行,请首先搭建好环境,如何搭建环境在项目的第二阶段里面。

概述

这是Java实现语音朗读相对全面的一篇博客,汲取大家之精华,进行总结,内容可能稍多,但是仔细看下来,保证你能够准确无误地实现语音朗读,我是一个Java初学者,换位思考,理解这篇博客对于神通广大的你来说,不算什么!本文章主要用于学习交流,欢迎大家点赞留言。

关键词

Java、Jacob、SAPI、EXE、语音朗读

主要环境

Windows、Java JDK/JRE 、sublime、eclipse
exe4j、PS、ICOFormat.8bi

主要知识点

(1) Jacob插件的使用。包括Sapi.SpVoice,ActiveXComponent,setProperty,Variant等的应用。
(2) GUI图形用户界面的使用。包括swing,awt,event包里的事件源、监视器、处理事件的接口等众多方法。

一、广泛搜集资料,学习专业知识,了解主体框架,打牢基础;

这一大条都是废话,大家可以自行忽略。
(1)在最初的准备阶段,我准备了好几种方案,并没有确定要用Java来实现项目,毕竟要以防万一。我首先准备了微软的Microsoft Speech SDK开发包,想借以C++来实现此项目,但是尝试之后以失败告终。
(2)上述过程失败之后,又尝试了与之类似的另一种方法,也是微软公司的,叫SAPI应用程序接口,不仅可以朗读语音,而且可以实现语音的识别和合成。但是很不幸,我又失败了。
(3)又尝试了微软的Visual Studio实现的MFC应用程序,具有可视化的界面,外表美观,可是失败了。
(4)最后敲定了是本学期我们刚刚学的Java,通过搜索资料得知,其jacob插件里的SAPI可实现语音朗读;与微软的SAPI的不同之处就是,Jacob里的SAPI我会用!那么这个项目也算是对新学知识的实践了,符合我们思政的鼓励思想。
(5)本来还想,为了功能的多样化,用Java实现知网论文的爬取或者时政新闻网站的数据爬取,方便用户查找资料并朗读。但是,事与愿违,尝试之后,代码根本跑不起来,错误连篇,漏洞百出。大概是因为这些网站的反爬虫机制做的太好了,所以就放弃了这个功能。
所有资料都可以去我个人主页的“我的收藏”“语音朗读”里面去找。

链接: 有关语音朗读资料.

二、尝试已经获得的资料,寻找突破口,确定发展方向;

搭建环境

最重要的环境就是Jacob搭建了。这个插件可以说是Java JDK/JRE的一个包,但是在最初安装JDK/JRE时是没有这个包的,所以需要自己配置。
具体配置过程可以参考以下网址或者看我精简后的配置过程:

链接: Jacob配置方法.
链接: Jacob介绍.

配置过程如下

目前最新版本1.18jacob-1.18下载,主要有三个文件:

链接: Jacob下载链接.

下载后解压得到
jacob.jar
jacob-1.18-x64.dll
jacob-1.18-x86.dll
dll文件有俩,对应windows 64 和32

1.将jacob-1.18-x64.dll放到64位的java的jdk或jre下的bin目录下

如果是32位系统就将jacob-1.18-x86.dll放到32位的jdk或jre下的bin目录下

2.将要操作的dll 文件放到相应的系统目录下
32位dll放到 C:\Windows\System32 目录下

64位dll放到 C:\Windows\SysWOW64 目录下

注:
搭建环境可能影响因素很多,我几次试错才成功。如果搭建错误,不妨试试把这些文件在JDK和JRE的bin目录下都放置一份。

Jacob简介

既然基本环境已经搭建成功,那么就可以学习使用插件和尝试用它编写代码了。Jacob包内的内容庞杂,Jacob是Java和com组件之间的桥梁,Jacob包里的Jacob.dll就是com组件,com组件的功能就是实现单一功能,就像用代码操控Word一样,我们不需要具体去实现它,而是去学习怎样去使用它。

三、在已有的方向上开始动手实践,试错调试,完成核心代码;

具体方法就是对Jacob SAPI的应用。

四、编辑可视化界面,为项目提供良好的视觉体验;

主要是利用Java GUI程序,运用其中的awt、event和swing包。这些都是Java环境自带的,无须额外下载。
实现后的界面:

五、完善代码,生成EXE程序,而后增加安全性和可移植性;

Java程序可以生成JAR包,然后由exe4j这个程序,通过设置一些版本号、作者签名来增加安全性后,会自动融合代码涉及的环境,生成EXE程序,就可以移植到别的普通电脑运行了。

核心代码

	//阅读文本文件
	    	
	    	ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice"); 

	    	//输入文件
	    	//
	    	labelShow.setText("文件路径需要用“ / ”间隔");
	        File srcFile = new File(str);
	       
	        //使用包装字符流读取文件
			/*
			 * BufferedReader br = new BufferedReader(new FileReader(srcFile));
			 * String content = br.readLine();
			 */
	        try {
    
      
	        	BufferedReader br = new BufferedReader(new FileReader(srcFile));
		        String content = br.readLine();
	           
		        // 音量 0-100  
	            sap.setProperty("Volume", new Variant(100));  
	            
	            // 语音朗读速度 -10 到 +10  
	            sap.setProperty("Rate", new Variant(2));  
	          
	            // 获取执行对象  
	            Dispatch sapo = sap.getObject();  
	           
	            // 执行朗读  
	            while (content != null) {
    
    
	                Dispatch.call(sapo, "Speak", new Variant(content));  
	                content = br.readLine();
	            }
	            Dispatch.call(sapo, "Speak", new Variant("朗读完了,休息一下吧"));
	    		labelShow.setText("朗读结束...");
	           
	    		// 关闭执行对象 
	            br.close();
	            sapo.safeRelease();  
	        } catch (Exception j) {
    
      
	            j.printStackTrace();  
	        } finally {
    
     
	           
	            // 关闭应用程序连接  
	            sap.safeRelease();  
	        } 
	    }

参考如下网址
链接: Java实现朗读文本文件.
链接: Java实现对输入的语句进行朗读.

EXE程序制作方法

制作方法可参考如下链接(实测可用)

链接: Java的JAR包导出和EXE程序制作1.
链接: EXE程序制作2.

制作完成后的EXE程序:
在这里插入图片描述

六、上传有关资源,撰写项目报告书,方便交流沟通和完善改进。

完整代码和程序下载地址:
可能需要积分,如果实在没有积分,可私聊我,我单独发给你。

链接: eclipse项目完整代码+EXE程序下载.

可能存在的问题

1.要选择功能,之后点击“开始阅读”,才能成功朗读。
2.如果阅读文本文件时,出现朗读乱码的情况,是因为记事本文件使用的是UTF_8编码,而这个程序还是GBK编码,可以在记事本的编辑—文本中更改为GBK格式。具体方法可以到网上去搜。
3.如果JAR包可以执行,而EXE程序不可执行,大概率是因为EXE程序制作过程出错,根据步骤,慢慢再来一遍就可以。

缺陷或改进

  1. 界面布局单一不美观
  2. 任务朗读没有感情、遇到特殊字符不知变通
  3. 功能单一,不能像小爱和小娜那样什么都会
  4. 只能在Windows平台下,平台单一
  5. 缺少选取文件的功能,只能手动输入文件路径(如果你会Java文本对话框这个问题就轻而易举了)
  6. 不能中断,只能关闭程序来强行中断
  7. 没有调节音量大小的功能

完整代码

注:包含几个Java文件,拷贝后运行时要注意。

//主类InputShow.java
public class InputShow {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		WindowsEvent show = new WindowsEvent ();
		PoliceListener police = new PoliceListener();
		show.setMyCommandListener(police);
		show.setTitle("语音朗读");
		show.setBounds(100,100,500,650);
	}

}
//窗口类WindowsEvent.java
import java.awt.*;
import javax.swing.*;

public class WindowsEvent extends JFrame{
    
    

	private static final long serialVersionUID = -5692167079052370018L;
	JTextArea textInput;
	//JScrollPane scroll;;
	JButton button;
	JLabel labelShow;
	JRadioButton radioWords;
	JRadioButton radioTxt;
	ButtonGroup group;
	MycommandListener listener;
	public WindowsEvent() {
    
    
		//构造函数
		init();
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

	}
	
	void init() {
    
    
		//初始化函数
		//setLayout(new GridLayout(4,1));//设置布局
		setLayout(new FlowLayout());
		//setLayout(null);
		
		//设置四个面板
		//显示文本区
		JPanel panelText = new JPanel();
		panelText.setSize(500, 350);
		//panelText.setLayout(null);
		add(panelText,BorderLayout.NORTH);
		//显示按钮面板
		JPanel panelButton = new JPanel();
		panelButton.setSize(500, 50);
		add(panelButton,BorderLayout.SOUTH);
		//显示选择面板
		JPanel panelChoice = new JPanel();
		panelChoice.setSize(500,50);
		add(panelChoice,BorderLayout.CENTER);
		//显示提示面板
		JPanel panelHint = new JPanel();
		panelHint.setSize(500, 50);
		add(panelHint);
		
		//JTextArea()设置文本区及格式
		textInput = new JTextArea(19,47) ;//分配文本区域
		textInput.setLineWrap(true);//随着文本区大小换行
		//JScrollPane scrollpane = new JScrollPane(textInput);
		//textInput = new JTextField(10);
		textInput.setFont(new Font("宋体", Font.PLAIN, 20));// 设置此标签的字体。
		panelText.add(new JScrollPane(textInput));
		
		//选择区
		group = new ButtonGroup();
		radioWords = new JRadioButton("输入语段朗读");
		radioWords.setFont(new Font("宋体", Font.PLAIN, 20));
		radioTxt = new JRadioButton("嵌入txt文件朗读");
		radioTxt.setFont(new Font("宋体", Font.PLAIN, 20));
		group.add(radioWords);
		group.add(radioTxt);
		panelChoice.add(radioWords);
		panelChoice.add(radioTxt);
		add(panelChoice);
		
		//按钮区
		button = new JButton("开始朗读");//添加按钮
		panelButton.add(button);
		button.setFont(new Font("宋体", Font.PLAIN, 20));
		add(panelButton);
		
		//标签区
		labelShow = new JLabel();//添加提示标签
		labelShow.setFont(new Font("宋体", Font.BOLD, 25));// 设置此标签的字体。
		panelHint.add(labelShow,BorderLayout.SOUTH);
		add(panelHint);
	}
	
	void setMyCommandListener(MycommandListener listener) {
    
    
		//安装监视器函数
		this.listener = listener;
		listener.setJButton(button);
		listener.setJTextArea(textInput);
		listener.setJLabel(labelShow);
		listener.setJRadioButton(radioWords);
		//listener.setJRadioButton(radioTxt);
		//添加监视器
		button.addActionListener(listener);
		//button是事件源,listener是监视器
	}
	
	
}
//监视器接口类 MycommandListener.java
import java.awt.event.*;
import javax.swing.*;

public interface MycommandListener extends ActionListener{
    
    
	//子接口
	//实现文本区域和按键的监视器
	public void setJTextArea(JTextArea area);
	public void setJButton(JButton button);
	public void setJLabel(JLabel label);
	public void setJRadioButton(JRadioButton radioButton);
}

//监视器实现类,核心代码块 PoliceListener.java
import java.awt.event.*;
import javax.swing.*;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import java.io.*;

public class PoliceListener implements MycommandListener{
    
    
	JTextArea textArea;
	//JScrollPane textArea;
	JButton readButton;
	JLabel labelShow;
	JRadioButton radioButton;
	public void setJTextArea(JTextArea area) {
    
    
		textArea = area;
	}
	
	public void setJButton(JButton button) {
    
    
		readButton = button;
	}
	
	public void setJLabel(JLabel label) {
    
    
		labelShow = label;
	}
	
	public void setJRadioButton(JRadioButton radioButton) {
    
    
		this.radioButton=radioButton;
	}
	
	public void actionPerformed(ActionEvent e) {
    
    
		// TODO Auto-generated method stub
		labelShow.setText(" ");
		String str = textArea.getText();
	    if(radioButton.isSelected()) {
    
    
	    	//阅读输入字段
	    	
	    	ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice");
	    	//获取朗读对象 
	    	Dispatch sapo = sap.getObject();
	    	try {
    
    
 
	    		// 音量 0-100
	    		sap.setProperty("Volume", new Variant(100));
	    		
	    		// 语音朗读速度 -10 到 +10
	    		sap.setProperty("Rate", new Variant(2));
	    		
	    		// 执行朗读
	    		Dispatch.call(sapo, "Speak", new Variant(str));
	    		Dispatch.call(sapo, "Speak", new Variant("朗读完了,休息一下吧"));
	    		labelShow.setText("朗读结束...");
	    	} catch (Exception i) {
    
    
	    		i.printStackTrace();
	    	} finally {
    
    
	    		sapo.safeRelease();//关闭执行对象
	    		sap.safeRelease();//关闭应用程序链接
	    		}
	    }else {
    
    
	    	//阅读文本文件
	    	
	    	ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice"); 

	    	//输入文件
	    	//
	    	labelShow.setText("文件路径需要用“ / ”间隔");
	        File srcFile = new File(str);
	       
	        try {
    
      
	        	BufferedReader br = new BufferedReader(new FileReader(srcFile));
		        String content = br.readLine();
	           
		        // 音量 0-100  
	            sap.setProperty("Volume", new Variant(100));  
	            
	            // 语音朗读速度 -10 到 +10  
	            sap.setProperty("Rate", new Variant(2));  
	          
	            // 获取执行对象  
	            Dispatch sapo = sap.getObject();  
	           
	            // 执行朗读  
	            while (content != null) {
    
    
	                Dispatch.call(sapo, "Speak", new Variant(content));  
	                content = br.readLine();
	            }
	            Dispatch.call(sapo, "Speak", new Variant("朗读完了,休息一下吧"));
	    		labelShow.setText("朗读结束...");
	           
	    		// 关闭执行对象 
	            br.close();
	            sapo.safeRelease();  
	        } catch (Exception j) {
    
      
	            j.printStackTrace();  
	        } finally {
    
     
	           
	            // 关闭应用程序连接  
	            sap.safeRelease();  
	        } 
	    }
	}
}


猜你喜欢

转载自blog.csdn.net/qq_43709785/article/details/106320397