Java 如何接收RTP流并提取音频?(爪哇) 简介

Java 如何接收RTP流并提取音频?(爪哇) 简介,java,audio,udp,rtp,codec,Java,Audio,Udp,Rtp,Codec,您好,我和一些同事已经没有办法通过RTP正确接收音频,然后提取音频流,希望有人能给我们指出正确的方向 背景: 音频通信通过多播地址和端口通过网络发送。此流量是UDP上的RTP。我们需要从数据包中提取音频,并将其打包到不同的UDP数据包中,然后将其发送到其他地方 到目前为止,我们的程序做了一些事情,它接收多播地址上接收到的数据包,并将数据复制到缓冲区中。然后,我们删除前12个字节的数据,因为我们知道这是RTP头 删除字节后,我们使用JavaJMF库将其转换为InputStream,并对其应用Aud

您好,我和一些同事已经没有办法通过RTP正确接收音频,然后提取音频流,希望有人能给我们指出正确的方向

背景: 音频通信通过多播地址和端口通过网络发送。此流量是UDP上的RTP。我们需要从数据包中提取音频,并将其打包到不同的UDP数据包中,然后将其发送到其他地方

到目前为止,我们的程序做了一些事情,它接收多播地址上接收到的数据包,并将数据复制到缓冲区中。然后,我们删除前12个字节的数据,因为我们知道这是RTP头

删除字节后,我们使用JavaJMF库将其转换为InputStream,并对其应用AudioFormat。然后将其发送到SourceDataLine进行本地播放,以验证音频质量

问题: 播放音频时,声音非常糟糕。我能听懂音频,但有很多噪音和爆裂声。我们不明白为什么听起来这么糟糕

我们使用VLC验证了RTP音频质量。它可以完美地播放,因此我们知道它与我们的代码有关。音频以G.711 PCMU编码,可使用VLC或内置RTP流分析器播放。我们已经弄乱了AudioFormat设置,但仍然无法让音频干净地播放

我们唯一的想法是音频采样太多,增加了大量噪音,或者格式不正确。我已经包括了一些文件的链接,如果试图重新创建我们的设置,这些文件可能会很有用。我们使用bittwist发送wireshark文件中捕获的数据包

捕获的音频播放听起来很糟糕:

G711 Wireshark数据包捕获:

具有良好音频的Wireshark音频提取:

Java代码 信贷:生锈的大脑/音乐

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);
    }
}
}
希望我已经充分解释了我们的问题,有人可以找到我们的问题所在,帮助我们回到正轨

谢谢,


奥斯汀

我只是在维基百科上查RTP。它表示头(您要丢弃的头)至少有12个字节。这对我来说意味着它的大小可以不同。此外,标题还包含序列信息和时间戳。UDP不维护信号的顺序。您是否正在处理排序,并且没有正确补偿丢失的音频数据?您能否从rtp负载转储pcmu数据并共享它。请确保pcmu音频数据播放的设置正确。(如果您的PCMU转储正确)您正在使用的AudioFormat构造函数将编码设置为线性PCM。您需要使用另一个构造函数,该构造函数将AudioFormat.Encoding作为参数,并使用AudioFormat.Encoding.ULAWI刚刚在wikipedia上查找RTP。它表示头(您要丢弃的头)至少有12个字节。这对我来说意味着它的大小可以不同。此外,标题还包含序列信息和时间戳。UDP不维护信号的顺序。您是否正在处理排序,并且没有正确补偿丢失的音频数据?您能否从rtp负载转储pcmu数据并共享它。请确保pcmu音频数据播放的设置正确。(如果您的PCMU转储正确)您正在使用的AudioFormat构造函数将编码设置为线性PCM。您需要使用另一个构造函数,该构造函数将AudioFormat.Encoding作为参数,并使用AudioFormat.Encoding.ULAW