您好,我本人和一些同事对通过RTP正确接收音频,然后提取音频流的想法已经用尽,希望在那里的人能为我们指明正确的方向。
音频流量是通过多播地址和端口通过网络发送的。此流量是基于UDP的RTP。我们需要从数据包中提取音频,然后将其打包到另一个UDP数据包中,然后将其发送到其他地方。
到目前为止,我们的程序目前正在做一些事情,它将接收在多播地址上接收到的数据包并将数据复制到缓冲区中。然后我们删除了前12个字节的数据,因为我们知道这是RTP标头。
在删除字节后,我们使用JAVA JMF库将其转换为InputStream并对其应用了AudioFormat。然后将其发送到SourceDataLine进行本地回放,以验证音频质量。
播放音频时,声音听起来很差。我可以辨认出音频,但是有很多噪音和破裂/爆裂声。我们无法弄清楚为什么听起来这么糟糕。
我们已经使用VLC验证了RTP音频质量。它可以完美播放,因此我们知道这与我们的代码有关。音频在G.711 PCMU中进行编码,可以使用RTP流分析器中内置的VLC或Wiresharks播放。我们搞砸了AudioFormat设置,但仍然无法使音频干净播放。
我们唯一的想法是音频采样过多,并添加了大量噪声,或者格式化不正确。我提供了一些文件的链接,这些文件可能在尝试重新创建我们的设置时很有用。我们使用bittwist发送wireshark文件中捕获的数据包。
捕获的声音播放听起来很糟糕: https://drive.google.com/open?id=1f4XiNELRVFUsMXgokNwUSnkVO10Ysq_T
G711 Wireshark数据包捕获: https://drive.google.com/open?id=1bZ54KH-KXeHd8CKQEVAU5vawoSiGWZFS
具有良好音频的Wireshark音频提取: https://drive.google.com/open?id=1-ZLXcoPesqsHdniiNqcCwUoZX50PP_mG
信用:RustedBrain / MusicHole
ByteArrayOutputStream byteOutputStream;
AudioFormat adFormat;
TargetDataLine targetDataLine;
AudioInputStream InputStream;
SourceDataLine sourceLine;
private AudioFormat getAudioFormat() {
float sampleRate = 8000.0F;
int sampleInbits = 8;
int channels = 1;
boolean signed = true;
boolean bigEndian = false;
return new AudioFormat(sampleRate, sampleInbits, channels, signed,
bigEndian);
}
public static void main(String args[]) {
new VUServer().runVOIP();
}
public void runVOIP() {
try {
MulticastSocket serverSocket = new MulticastSocket(22202);
InetAddress group = InetAddress.getByName("239.1.1.1");
serverSocket.joinGroup(group);
byte[] receiveData = new byte[10000];
while (true) {
DatagramPacket receivePacket = new
DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
System.out.println("RECEIVED: " + receivePacket.getAddress().getHostAddress() + " " + receivePacket.getPort() + " " + "Packet Size: " + receivePacket.getLength());
try {
byte temp[] = receivePacket.getData();
byte[] filteredByteArray = Arrays.copyOfRange(temp, 12, receivePacket.getLength() - 12);
byte audioData[] = filteredByteArray.clone();
InputStream byteInputStream = new ByteArrayInputStream(audioData);
AudioFormat adFormat = getAudioFormat();
InputStream = new AudioInputStream(byteInputStream, adFormat, audioData.length / adFormat.getFrameSize());
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, adFormat);
sourceLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
sourceLine.open(adFormat);
sourceLine.start();
Thread playThread = new Thread(new PlayThread());
playThread.start();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
class PlayThread extends Thread {
byte tempBuffer[] = new byte[10000];
public void run() {
try {
int cnt;
while ((cnt = InputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
if (cnt > 0) {
sourceLine.write(tempBuffer, 0, cnt);
}
}
// sourceLine.drain();
// sourceLine.close();
} catch (Exception e) {
System.out.println(e);
System.exit(0);
}
}
}
希望我已经对我们的问题进行了充分的解释,以便有人可以找到我们搞砸的地方,并帮助我们重回正轨。
谢谢
奥斯丁