我正在制作类似skype的程序。我有一个“ VoiceChat ”类来处理语音聊天连接。我有一个“ ClientAudio ”类来处理客户端音频输出。我还有一个“ ClientAudioRec ”来处理从服务器接收音频并播放它。在“ ClientAudio ”类中,我将音频数据存储在缓冲区中,直到它已满,以尝试减少延迟。然后我把它发送到服务器。如果我在呼叫中有两个人,那么除非缓冲区是1000,否则它会滞后。当我在呼叫中添加另一个人时,它会滞后以至于你无法理解任何人。但是我不希望每次有人加入时都扩展缓冲区,因为1000已经是两秒钟的延迟了。如果有人知道如何减少滞后或使其几乎立即真正有用。谢谢你提前!!!
VoiceChat(服务器端)
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class VoiceChat extends Thread {
private Socket s;
private ObjectOutputStream out;
private ObjectInputStream in;
private Thread acceptThread;
private int VoicePort;
private int num;
public VoiceChat(Socket sVoice, int VoicePort, Thread acceptThread) {
s = sVoice;
this.VoicePort = VoicePort;
this.acceptThread = acceptThread;
num = chat.threads.indexOf(this.acceptThread)+1;
try {
out = new ObjectOutputStream(s.getOutputStream());
in = new ObjectInputStream(s.getInputStream());
if(VoicePort <= 65511) {
chat.users1_Voice.add(out);
}else {
chat.users2.add(out);
}
} catch (IOException e) {
System.out.println("ERROR2");
e.printStackTrace();
}
}
public void run() {
int bytesRead = 0;
byte[] inBytes = new byte[100];
while(bytesRead != -1) {
try {
bytesRead = in.read(inBytes, 0, inBytes.length);
}catch (IOException e) {
System.out.println("ERROR2");
if(VoicePort <= 65511) {
chat.users1_Voice.remove(out);
}else {
chat.users2.remove(out);
}
}
if(bytesRead > 0) {
System.out.println(chat.users1_Voice);
send(inBytes, bytesRead, out);
System.out.println("SENDING DATA");
}
}
}
public void send(byte[] soundData, int bytesRead, ObjectOutputStream out) {
if(VoicePort <= 65511) {
for(ObjectOutputStream o : chat.users1_Voice) {
try {
if(o != out) {
o.write(soundData, 0, bytesRead);
o.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
for(ObjectOutputStream o : chat.users2) {
try {
if(o != out) {
o.write(soundData, 0, bytesRead);
o.flush();
}
} catch (IOException e) {
}
}
}
}
}
ClientAudio
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
public class ClientAudio implements Runnable {
private ObjectOutputStream out = null;
private AudioFormat af;
private TargetDataLine microphone;
ClientAudio(AudioFormat af) {
this.af = af;
}
public void run() {
try {
client.voiceSocket = new Socket("***IP***", client.VoicePort);
Thread car = new Thread(new ClientAudioRec(af));
car.start();
out = new ObjectOutputStream(client.voiceSocket.getOutputStream());
DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
microphone = (TargetDataLine)AudioSystem.getLine(info);
microphone.open(af);
microphone.start();
int bytesRead = 0;
int offset = 0;
byte[] soundData = new byte[1000];
while(bytesRead != -1 && client.callRunning == true) {
bytesRead = microphone.read(soundData, 0, soundData.length);
if(bytesRead >= 0) {
offset += bytesRead;
if(offset == soundData.length) {
out.write(soundData, 0, bytesRead);
offset = 0;
}
}
}
microphone.close();
try {
client.voiceSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("Client Audio Stopped Because Client Disconnected From Call");
} catch (IOException | LineUnavailableException e) {
microphone.close();
try {
client.voiceSocket.close();
} catch (IOException e1) {
System.out.println("Plug Microphone In...");
}
System.out.println("Client Audio Stopped...");
}
}
}
ClientAudioRec
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
public class ClientAudioRec implements Runnable {
private SourceDataLine inSpeaker = null;
private AudioFormat audioformat;
private ObjectInputStream in;
ClientAudioRec(AudioFormat af) {
audioformat = af;
try {
in = new ObjectInputStream(client.voiceSocket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioformat);
try {
inSpeaker = (SourceDataLine)AudioSystem.getLine(info);
inSpeaker.open(audioformat);
} catch (LineUnavailableException e1) {
System.out.println("ERROR");
e1.printStackTrace();
}
int bytesRead = 0;
byte[] inSound = new byte[100000];
inSpeaker.start();
while(bytesRead != -1 && client.callRunning == true) {
try{bytesRead = in.read(inSound, 0, inSound.length);} catch (Exception e){
inSpeaker.close();
System.out.println("Speaker Closed");
}
if(bytesRead >= 0) {
inSpeaker.write(inSound, 0, bytesRead);
}
}
inSpeaker.close();
System.out.println("Speaker Closed Because Client Disconneted From Call");
}
}