java Android:通过 TCP 套接字流式传输音频
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2749236/
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
Android: Streaming audio over TCP Sockets
提问by Chaitanya
For my app, I need to record audio from MIC on an Android phone, and send it over TCP to the other android phone, where it needs to be played.
对于我的应用程序,我需要在 Android 手机上录制来自 MIC 的音频,然后通过 TCP 将其发送到需要播放的另一部 Android 手机。
I am using AudioRecordand AudioTrackclass. This works great with a file - write audio to the file using DataOutputStream, and read from it using DataInputStream.
我正在使用AudioRecord和AudioTrack上课。这适用于文件 - 使用 将音频写入文件DataOutputStream,并使用DataInputStream.
However, if I obtain the same stream from a socket instead of a File, and try writing to it, I get an exception.
但是,如果我从套接字而不是文件获取相同的流,并尝试写入它,则会出现异常。
I am at a loss to understand what could possibly be going wrong. Any help would be greatly appreciated.
我无法理解可能会出现什么问题。任何帮助将不胜感激。
EDIT: The problem is same even if I try with larger buffer sizes (65535 bytes, 160000 bytes).
编辑:即使我尝试使用更大的缓冲区大小(65535 字节,160000 字节),问题也是一样的。
This is the code:
这是代码:
Recorder:
录音机:
int bufferSize = AudioRecord.getMinBufferSize(11025, , AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT);
AudioRecord recordInstance = new AudioRecord(MediaRecorder.AudioSource.MIC, 11025, AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize);
byte[] tempBuffer = new byte[bufferSize];
recordInstance.startRecording();
while (/*isRecording*/) {
bufferRead = recordInstance.read(tempBuffer, 0, bufferSize);
dataOutputStreamInstance.write(tempBuffer);
}
The DataOutputStream above is obtained as:
上面的 DataOutputStream 获得如下:
BufferedOutputStream buff = new BufferedOutputStream(out1); //out1 is the socket's outputStream
DataOutputStream dataOutputStreamInstance = new DataOutputStream (buff);
Could you please have a look, and let me know what is it that I could be doing wrong here?
你能看看吗,让我知道我在这里做错了什么?
Thanks,
谢谢,
采纳答案by Chaitanya
I got this working, with some help, and only partially.
我在一些帮助下完成了这项工作,而且只是部分工作。
I started off with the code at http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html, changed File's streams to Socket's streams, and changed the isAvailable() to if(inputStream.read(byteArray) != -1).
我从http://emeadev.blogspot.com/2009/09/raw-audio-manipulation-in-android.html的代码开始,将 File 的流更改为 Socket 的流,并将 isAvailable() 更改为 if(inputStream .read(byteArray) != -1)。
Live streaming of audio over TCP is happening now.
现在正在通过 TCP 实时流式传输音频。
However,
然而,
All I hear at the other end is noise, and I am now hunting for correct set of parameters for AudioRecorder and AudioTrack - the frequency, channel config and encoding, audio source etc.
我在另一端听到的只是噪音,我现在正在寻找 AudioRecorder 和 AudioTrack 的正确参数集 - 频率、通道配置和编码、音频源等。
If you have any idea about this, please let me know.
如果您对此有任何想法,请告诉我。
Thanks,
谢谢,
EDIT: It was a stupid error on my part. In addition to all I have said above, use inputStream on player side and outputStream on recorder side, and byte arrays instead of shorts and it will work. :)
编辑:这对我来说是一个愚蠢的错误。除了我上面所说的之外,在播放器端使用 inputStream ,在记录器端使用 outputStream ,以及字节数组而不是 shorts ,它会起作用。:)
回答by M?nh Quy?t Nguy?n
The problem is lying here:
问题出在这里:
bufferRead = recordInstance.read(tempBuffer, 0, bufferSize);
dataOutputStreamInstance.write(tempBuffer);
You read bufferReadworth of bytes but you attempt to write whole buffer to the output stream.
您读取了bufferRead大量字节,但您尝试将整个缓冲区写入输出流。
To improve the recording process, you may consider following points:
为了改进记录过程,您可以考虑以下几点:
- Enable
NoiseSuppressor(since API 16) - Enable
AcousticEchoCanceler(since API 16) - Increase initial buffersize and should read a chunk of bytes smallerthan initial buffersize for smoother audiostream
- Switch to UDP. Streaming is UDP job.
- 启用
NoiseSuppressor(自 API 16 起) - 启用
AcousticEchoCanceler(自 API 16 起) - 增加初始缓冲区大小,应该读取的字节块更小的比初始缓冲区大小流畅的语音串流
- 切换到 UDP。流式传输是 UDP 作业。
Here is my setup for my previous android app:
这是我以前的 android 应用程序的设置:
// Calculate minimum buffer size
int minBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
// Initialize AudioRecord for getting audio from device
AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSize * 4);
if (API > API 16) {
if (NoiseSuppressor.isAvailable()) {
NoiseSuppressor.create(recorder.getAudioSessionId()).setEnabled(true);
}
if (AcousticEchoCanceler.isAvailable()) {
AcousticEchoCanceler.create(recorder.getAudioSessionId()).setEnabled(true);
}
}
....
byte[] tempBuffer = new byte[minBufferSize];
while (/*isRecording*/) {
bufferRead = recordInstance.read(tempBuffer, 0, minBufferSize);
dataOutputStreamInstance.write(tempBuffer, 0, bufferRead);
}
回答by dsandler
Without knowing the specific exception you're getting, it's hard to know exactly what's wrong. It would also help to see the code you're using to create out1(that is, your socket code).
如果不知道您得到的具体异常,就很难确切知道出了什么问题。查看您用来创建的代码out1(即您的套接字代码)也会有所帮助。
Something you might want to pay attention to is the amount of data read from recordInstance.read(); you might not get a whole bufferSize-sized chunk of data out of it, so you need to take care only to write bytes 0through bufferRead-1to your output socket.
您可能需要注意的是从中读取的数据量recordInstance.read();你可能无法得到一个整体bufferSize出来的数据尺度的块,所以你需要照顾只会写字节0,通过bufferRead-1你的输出插口。

