针对项目功能点的创新:
大部分都是利用java sound实现
1.实现语音播报:
当有新用户进入聊天室时系统自动播报欢迎进入
2.对文字消息进行语音播放:
纯文本消息可以使用语音播报
package service;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
/**
* 语音播报(window)
* @author Eric
* @create 2022-07-16 16:45
*/
public class staticTools {
/**【语音播报方法】**/
public static boolean speakingText(String readText){
boolean isFinish = true;
ActiveXComponent sap = new ActiveXComponent("Sapi.SpVoice");
try {
sap.setProperty("Volume",new Variant(100)); // 音量 0-100
sap.setProperty("Rate",new Variant(-1)); // 语音朗读速度 -10 到 +10
Dispatch sapo = sap.getObject(); // 获取执行对象
Dispatch.call(sapo,"Speak",new Variant(readText)); // 执行朗读
sapo.safeRelease(); // 关闭执行对象
}catch (Exception e){
isFinish = false;
e.printStackTrace();
}finally {
sap.safeRelease(); // 关闭执行对象
}
return isFinish;
}
// public static void main(String[] args) {
// staticTools.speakingText("您有一笔新的订单,请注意查收");
// }
}
3.实现语音发送:
点击按钮开始录音,结束录音后录音保存为文件自动发送给好友(由于是文件,操作起来不是很方便)
@FXML
void yuyinbuttonAction(ActionEvent event) throws IOException {
Button button = (Button) event.getSource();
if (button.getText().equals("开始录音")) {
startRecording();
button.setText("停止录音");
} else {
stopRecording();
button.setText("开始录音");
Date queueDate = new Date();
SimpleDateFormat queueDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String now2 = queueDateFormat.format(queueDate);
Platform.runLater(()-> {
;
Message message = new Message();
message.content = "语音:";//自定义文件名
message.type = 3;
message.isperson = 1;
message.recieveid = user.id;
message.sendid = owner.id;
message.time = now2;
message.filepath=audioFile.getPath();
try {
Connection.oos.writeObject(MarkTool.uploadfile);
Connection.oos.writeObject(message);
Connection.oos.writeObject(MarkTool.uploadfile);
new Thread(new SendFileThread(audioFile)).start();//开启线程上传文件
//将发送的文件显示在上面
ChatBubble chatBubble = new ChatBubble(message, owner);
chatListview.getItems().add(chatBubble); // 将消息添加到ListView
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
}
private void startRecording() {
try {
// 设置录音格式
AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
// 检查系统是否支持所需的音频格式
if (!AudioSystem.isLineSupported(info)) {
System.out.println("不支持所需的音频格式");
return;
}
// 获取音频输入设备
audioInput = (TargetDataLine) AudioSystem.getLine(info);
audioInput.open(format);
audioInput.start();
// 创建一个新的线程来执行录音
Thread recordingThread = new Thread(() -> {
try {
// 创建音频输入流
AudioInputStream audioStream = new AudioInputStream(audioInput);
// 设置录音文件路径和名称
audioFile = new File("recordedAudio.wav");
// 开始录音
AudioSystem.write(audioStream, fileType, audioFile);
} catch (IOException e) {
e.printStackTrace();
}
});
recordingThread.start();
} catch (LineUnavailableException e) {
e.printStackTrace();
}
}
private void stopRecording() {
if (audioInput != null) {
audioInput.stop();
audioInput.close();
// 在录音结束后保存录音文件
saveAudioToFile();
}
}
private void saveAudioToFile() {
// 确保文件已经创建并且录音文件不为空
if (audioFile != null && audioFile.exists()) {
// 将录音文件移动到所需的位置,这里简单地将其保存在用户的主目录下
String userHome = System.getProperty("user.home");
File destinationFile = new File(userHome + File.separator + "recordedAudio.wav");
try {
if (audioFile.renameTo(destinationFile)) {
System.out.println("录音已保存至:" + destinationFile.getAbsolutePath());
} else {
System.out.println("无法将录音保存至目标位置。");
}
} catch (SecurityException e) {
System.out.println("没有权限将录音保存至目标位置。");
e.printStackTrace();
}
} else {
System.out.println("录音文件不存在或为空。");
}
}
4.语音聊天:
新开线程进行语音聊天,服务端作为中转实现客户端之间的语音聊天
//发送语音聊天新建连接
ServerSocket serSock=new ServerSocket(6000);
Socket cli=serSock.accept();
Playback player=new Playback(cli);
player.start();
//接收连接
Socket cli=new Socket("127.0.0.1",6000);
Capture cap=new Capture(cli);
cap.start();
//Playback.java
import java.io.*;
import javax.sound.sampled.*;
import java.net.*;
/**
* Title: VoiceChat
* Description: 输出音频(放音程序)
* Copyright: Copyright (c) 2001
* Company:
* @author
* @version 1.0
*/
class Playback implements Runnable {
final int bufSize = 16384;
SourceDataLine line;
Thread thread;
Socket s;
Playback(Socket s){//构造器 取得socket以获得网络输入流
this.s=s;
}
public void start() {
thread = new Thread(this);
thread.setName("Playback");
thread.start();
}
public void stop() {
thread = null;
}
public void run() {
AudioFormat format =new AudioFormat(8000,16,2,true,true);//AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)
BufferedInputStream playbackInputStream;
try {
playbackInputStream=new BufferedInputStream(new AudioInputStream(s.getInputStream(),format,2147483647));//封装成音频输出流,如果网络流是经过压缩的需在此加套解压流
}
catch (IOException ex) {
return;
}
DataLine.Info info = new DataLine.Info(SourceDataLine.class,format);
try {
line = (SourceDataLine) AudioSystem.getLine(info);
line.open(format, bufSize);
} catch (LineUnavailableException ex) {
return;
}
byte[] data = new byte[1024];//此处数组的大小跟实时性关系不大,可根据情况进行调整
int numBytesRead = 0;
line.start();
while (thread != null) {
try{
numBytesRead = playbackInputStream.read(data);
line.write(data, 0,numBytesRead);
} catch (IOException e) {
break;
}
}
if (thread != null) {
line.drain();
}
line.stop();
line.close();
line = null;
}
}
//Capture.java
import java.io.*;
import javax.sound.sampled.*;
import java.net.*;
/**
* Title: VoiceChat
* Description: 音频捕捉(录音程序)
* Copyright: Copyright (c) 2001
* Company:
* @author
* @version 1.0
*/
class Capture implements Runnable {
TargetDataLine line;
Thread thread;
Socket s;
BufferedOutputStream captrueOutputStream;
Capture(Socket s){//构造器 取得socket以获得网络输出流
this.s=s;
}
public void start() {
thread = new Thread(this);
thread.setName("Capture");
thread.start();
}
public void stop() {
thread = null;
}
public void run() {
try {
captrueOutputStream=new BufferedOutputStream(s.getOutputStream());//建立输出流 此处可以加套压缩流用来压缩数据
}
catch (IOException ex) {
return;
}
AudioFormat format =new AudioFormat(8000,16,2,true,true);//AudioFormat(float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian)
DataLine.Info info = new DataLine.Info(TargetDataLine.class,format);
try {
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format, line.getBufferSize());
} catch (Exception ex) {
return;
}
byte[] data = new byte[1024];//此处的1024可以情况进行调整,应跟下面的1024应保持一致
int numBytesRead=0;
line.start();
while (thread != null) {
numBytesRead = line.read(data, 0,1024);//取数据(1024)的大小直接关系到传输的速度,一般越小越快,
try {
captrueOutputStream.write(data, 0, numBytesRead);//写入网络流
}
catch (Exception ex) {
break;
}
}
line.stop();
line.close();
line = null;
try {
captrueOutputStream.flush();
captrueOutputStream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}