通过TCP发送音频流,UnsupportedAudioFileException

我成功地通过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套接字发送音频流。

服务器:服务器只传输声音文件的字节。 没有涉及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"); } } 

客户端:客户端可以播放通过命令行传递的声音文件,以便进行测试:

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

没有参数调用它连接到服务器并播放通过套接字接收的文件:

 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; } } 

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文档,深入了解播放音频的基础知识。

注意

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

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