java 通过 TCP 发送音频流,UnsupportedAudioFileException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17044644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sending audio stream over TCP, UnsupportedAudioFileException
提问by mini
I have succeeded with sending and reading text and images data over TCP sockets. But I am unable to sending and reading audio stream data.
我已经成功地通过 TCP 套接字发送和读取文本和图像数据。但我无法发送和读取音频流数据。
sample code at server:
服务器上的示例代码:
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;
}
}
sample code at client:
客户端的示例代码:
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();
}
}
}
Where I am getting Exception as
我在哪里得到异常作为
javax.sound.sampled.UnsupportedAudioFileException: could not get audio input stream from input stream
at javax.sound.sampled.AudioSystem.getAudioInputStream(Unknown Source)
Where I have observed that server is sending 35394bytes data to client, But at client side we are receiving 8192 bytes data. I am unable to understanding why bytes are missing at client side.
我观察到服务器正在向客户端发送 35394 字节的数据,但在客户端,我们收到了 8192 字节的数据。我无法理解为什么客户端缺少字节。
Please help me how to send audio stream over TCP Sockets.
请帮助我如何通过 TCP 套接字发送音频流。
回答by wero
The Server:The server just streams the bytes of a sound file. No AudioSytem involved. Pass the sound file as argument:
服务器:服务器只是流式传输声音文件的字节。不涉及 AudioSystem。将声音文件作为参数传递:
java AudioServer "C:/Users/Public/Music/Sample Music/adios.wav"
Code for class AudioServer:
类 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:The client can play a soundfile passed via the command-line for testing if it works:
客户端:客户端可以播放通过命令行传递的声音文件以测试其是否有效:
java AudioClient "C:/Users/Public/Music/Sample Music/adios.wav"
Called with no argument it connects to the server and plays the file received via an Socket:
不带参数调用它连接到服务器并播放通过套接字接收的文件:
java AudioClient
Code:
代码:
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();
}
}
}
A utility class used by AudioServer and AudioClient:
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;
}
}
回答by Kunjan Thadani
The bytes will be received completely as TCP is reliable. There is another small issue. You need to play the received audio from the audio stream, only creating an audio input stream will not play it. There can be different possible techniques for playing the audio received. You can use a Clipor SourceDataLinefrom the Java Sound API. Also, do not create the AudioInputStream multiple times. Simply create it once and use it.
由于 TCP 是可靠的,因此字节将被完全接收。还有一个小问题。您需要从音频流中播放接收到的音频,仅创建音频输入流不会播放它。可以有不同的可能技术来播放接收到的音频。您可以使用夹子或SourceDataLine的从Java声音API。此外,不要多次创建 AudioInputStream。只需创建一次并使用它。
Here's one of the possible solution you can use for playing the received audio.
这是您可以用来播放接收到的音频的可能解决方案之一。
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);
}
}
}
You may need a different implementation based on your requirement. This is just a demonstration on how you can use the AudioInputStreamfor playing audio using Clip. You may notice quite a few changes in the code I have posted. I hope you understand this well.
根据您的要求,您可能需要不同的实现。这只是关于如何使用AudioInputStream使用Clip播放音频的演示。您可能会注意到我发布的代码中有很多更改。我希望你能很好地理解这一点。
You may refer the Java Sound API docs to dive into the basics of playing audio.
您可以参考 Java Sound API 文档来深入了解播放音频的基础知识。
NOTE:
注意:
Just for your knowledge, you may need to implement a listenerso that the program do not get closed before the audio clip finishes playing. In the current implementation it won't happen due to the loop used. But it is better to use a listener. You may refer this post.
You can also read the audio data into byte[] and then play it as soon as it is received. The implementation would change slightly.
仅就您的知识而言,您可能需要实现一个侦听器,以便程序在音频剪辑完成播放之前不会关闭。在当前的实现中,由于使用了循环,它不会发生。但最好使用侦听器。你可以参考这篇文章。
也可以将音频数据读入byte[],收到后立即播放。实现会略有变化。