首页 文章

通过TCP发送音频流,UnsupportedAudioFileException

提问于
浏览
10

我成功地通过TCP套接字发送和读取文本和图像数据 . 但我无法发送和读取音频流数据 .

服务器上的示例代码:

public class ServerAudio {
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        try {
            ServerSocket serverSocker = new ServerSocket();
            Socket client = null;
            serverSocker.bind(new InetSocketAddress(6666));
            if (serverSocker.isBound()) {
                client = serverSocker.accept();
                OutputStream out = client.getOutputStream();
                while (true) {
                    AudioInputStream ain = testPlay("C:/Users/Public/Music/Sample Music/adios.wav");
                    if (ain != null) {
                        AudioSystem.write(ain, AudioFileFormat.Type.WAVE, out);
                    }
                }
            }
            serverSocker.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static AudioInputStream testPlay(String filename) {
        AudioInputStream din = null;
        try {
            File file = new File(filename);
            AudioInputStream in = AudioSystem.getAudioInputStream(file);
            System.out.println("Before :: " + in.available());

            AudioFormat baseFormat = in.getFormat();
            AudioFormat decodedFormat =
                    new AudioFormat(AudioFormat.Encoding.PCM_UNSIGNED, baseFormat.getSampleRate(),
                            8, baseFormat.getChannels(), baseFormat.getChannels(),
                            baseFormat.getSampleRate(), false);
            din = AudioSystem.getAudioInputStream(decodedFormat, in);
            System.out.println("After :: " + din.available());
            return din;
        } catch (Exception e) {
            // Handle exception.
            e.printStackTrace();
        }
        return din;
    }
}

客户端的示例代码:

public class RDPPlayAudioBytes {
    private static Socket socket;
    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        // SocketAddress socketAddress = new InetSocketAddress("172.19.1.50", 4444);
        try {
            Socket socket = new Socket("172.19.0.109", 6666);
            // socket.connect(socketAddress, 10000);
            if (socket != null && socket.isConnected()) {
                InputStream inputStream = socket.getInputStream();
                // DataInputStream din=new DataInputStream(inputStream);
                while (inputStream != null) {
                    if (inputStream.available() > 0) {
                        System.out.println(inputStream.available());
                        InputStream bufferedIn = new BufferedInputStream(inputStream);
                        System.out.println("********** Buffred *********" + bufferedIn.available());
                        AudioInputStream ais = AudioSystem.getAudioInputStream(bufferedIn);
                    }
                }
            }


        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } /*
           * catch (LineUnavailableException e) { // TODO Auto-generated catch block
           * e.printStackTrace(); }
           */catch (UnsupportedAudioFileException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

我在哪里得到例外

javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
    at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)

我观察到服务器正在向客户端发送35394字节数据,但在客户端,我们正在接收8192字节数据 . 我无法理解为什么客户端缺少字节 .

请帮我如何通过TCP套接字发送音频流 .

2 回答

  • 5

    The Server: 服务器只是流式传输声音文件的字节 . 没有涉及AudioSytem . 将声音文件作为参数传递:

    java AudioServer "C:/Users/Public/Music/Sample Music/adios.wav"
    

    AudioServer类的代码:

    import java.io.*;
    import java.net.*;
    
    public class AudioServer {
        public static void main(String[] args) throws IOException {
            if (args.length == 0)
                throw new IllegalArgumentException("expected sound file arg");
            File soundFile = AudioUtil.getSoundFile(args[0]);
    
            System.out.println("server: " + soundFile);
    
            try (ServerSocket serverSocker = new ServerSocket(6666); 
                FileInputStream in = new FileInputStream(soundFile)) {
                if (serverSocker.isBound()) {
                    Socket client = serverSocker.accept();
                    OutputStream out = client.getOutputStream();
    
                    byte buffer[] = new byte[2048];
                    int count;
                    while ((count = in.read(buffer)) != -1)
                        out.write(buffer, 0, count);
                }
            }
    
            System.out.println("server: shutdown");
        }
    }
    

    The client: 客户端可以播放通过命令行传递的声音文件,以便测试是否有效:

    java AudioClient "C:/Users/Public/Music/Sample Music/adios.wav"
    

    在没有参数的情况下调用它连接到服务器并播放通过Socket接收的文件:

    java AudioClient
    

    码:

    import java.io.*;
    import java.net.*;
    import javax.sound.sampled.*;
    
    
    public class AudioClient {
        public static void main(String[] args) throws Exception {
            if (args.length > 0) {
                // play a file passed via the command line
                File soundFile = AudioUtil.getSoundFile(args[0]);
                System.out.println("Client: " + soundFile);
                try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(soundFile))) {
                    play(in);
                }
            }
            else {
                // play soundfile from server
                System.out.println("Client: reading from 127.0.0.1:6666");
                try (Socket socket = new Socket("127.0.0.1", 6666)) {
                    if (socket.isConnected()) {
                        InputStream in = new BufferedInputStream(socket.getInputStream());
                        play(in);
                    }
                }
            }
    
            System.out.println("Client: end");
        }
    
    
        private static synchronized void play(final InputStream in) throws Exception {
            AudioInputStream ais = AudioSystem.getAudioInputStream(in);
            try (Clip clip = AudioSystem.getClip()) {
                clip.open(ais);
                clip.start();
                Thread.sleep(100); // given clip.drain a chance to start
                clip.drain();
            }
        }
    }
    

    AudioServer和AudioClient使用的实用程序类:

    import java.io.File;
    
    public class AudioUtil {
        public static File getSoundFile(String fileName) {
            File soundFile = new File(fileName);
            if (!soundFile.exists() || !soundFile.isFile())
                throw new IllegalArgumentException("not a file: " + soundFile);
            return soundFile;
        }
    }
    
  • 8

    TCP可靠时将完全接收字节 . 还有一个小问题 . 您需要播放音频流中接收的音频,只创建音频输入流不会播放 . 可以存在用于播放所接收的音频的不同可能技术 . 您可以使用 Java Sound API 中的 ClipSourceDataLine . 另外,不要多次创建AudioInputStream . 只需创建一次并使用它 .

    这是您可以用来播放接收音频的可能解决方案之一 .

    public class RDPPlayAudioBytes {
    
    private static Socket socket;
    private static BufferedInputStream inputStream;
    
    /**
     * @param args
     * @throws javax.sound.sampled.LineUnavailableException
     */
    public static void main(String[] args) throws LineUnavailableException {
        // TODO Auto-generated method stub
        // SocketAddress socketAddress = new InetSocketAddress("172.19.1.50", 4444);
        try {
            socket = new Socket("127.0.0.1", 6666);
    
            if (socket.isConnected()) {
    
                inputStream = new BufferedInputStream(socket.getInputStream());
    
                Clip clip = AudioSystem.getClip();
                AudioInputStream ais = AudioSystem.getAudioInputStream(inputStream);
                clip.open(ais);
                clip.start();
    
                while (inputStream != null) {
                    if (clip.isActive()) {
    
                        System.out.println("********** Buffred *********" + inputStream.available());
    
                    }
                }
    
            }
    
        } catch (IOException | UnsupportedAudioFileException e) {
            System.err.println(e);
        }
    }
    }
    

    您可能需要根据您的要求实施不同的实施方案 . 这只是一个演示如何使用 AudioInputStream 使用 Clip 播放音频 . 您可能会注意到我发布的代码中有很多更改 . 我希望你能理解这一点 .

    您可以参考Java Sound API文档以深入了解playing audio的基础知识 .

    NOTE

    • 为了您的知识,您可能需要 implement a listener ,以便在音频剪辑播放完毕之前程序不会关闭 . 在当前的实现中,由于使用了循环,它不会发生 . 但是最好使用一个监听器 . 你可以参考this post .

    • 您还可以将音频数据读入byte [],然后在收到后立即播放 . 实施将略有改变 .

相关问题