我有一个在本地主机上运行的流媒体服务器。当我尝试从我的Android应用程序中流式传输音频时。我大多数时候都会听到静电噪音(就像你在收音机里听到的那种)。有时完整的音频是静态噪声,有时是其中的一部分,而有时音频播放得很好,所以我不确定哪里出了问题。
下面是我的android应用程序的流代码:
new Thread(
new Runnable() {
@Override
public void run() {
try {
URI uri = URI.create("http://192.168.1.6:5000/api/tts");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("x-access-token", credentials.getAccessToken());
urlConnection.setRequestProperty("Accept", "*");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream());
String body = "{\"text\": \"" + text + "\", \"ttsLang\": \"" + language + "\"}";
Log.d("TTS_HTTP", body);
osw.write(body);
osw.flush();
osw.close();
Log.d("TTS_OUT", credentials.getAccessToken());
Log.d("TTS_OUT", urlConnection.getResponseCode() + " " + urlConnection.getResponseMessage());
// define the buffer size for audio track
int SAMPLE_RATE = 16000;
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
bufferSize *= 2;
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize*2,
AudioTrack.MODE_STREAM);
byte[] buffer = new byte[bufferSize];
InputStream is = urlConnection.getInputStream();
int count;
audioTrack.play();
while ((count = is.read(buffer, 0, bufferSize)) > -1) {
Log.d("TTS_COUNT", count + "");
audioTrack.write(buffer, 0, count);
}
is.close();
audioTrack.stop();
audioTrack.release();
} catch (IOException e) {
e.printStackTrace();
}
}
}
).start();
请帮我修复代码来解决这个问题。我不能像我之前描述的那样正确听到声音。
此外,服务器响应也很好,因为我可以使用Python代码将其保存到文件中。保存的文件正在正常播放。
>>> import requests
>>> import wave
>>> with wave.open("output.wav", "wb") as f:
... f.setframerate(16000) # 16khz
... f.setnchannels(1) # mono channel
... f.setsampwidth(2) # 16-bit audio
... res = requests.post("http://192.168.1.6:5000/api/tts", headers={"x-access-token": token}, json={"text": "Hello, would you like to have some tea", "ttsLang": "en-us"}, stream=True)
... for i in res.iter_content(chunk_size=16*1024):
... f.writeframes(i)
...
更新:将输入流写入文件,然后从一个文件播放到另一个音轨,效果很好……
发布于 2019-05-09 04:45:06
最后,我解决了这个问题。事实证明,AudioTrack
不喜欢向其写入不一致的数据量,并因此而产生静态噪声。这是之前写入AudioTrack
的字节计数序列,导致问题1248
、3439
、5152
、5152
、3834
、...、823
(不一致)。因此,我查看了DataInputStream
的readFully
方法,并使用它解决了静态噪声问题。字节计数序列现在看起来像5152
,5152
,5152
,...,5152
(一致)。但现在的问题是读取由于EOFException
而被跳过的剩余字节。所以我不得不实现我自己的方法来解决这个问题。
public class TTSInputStream extends DataInputStream {
public TTSInputStream(InputStream in) {
super(in);
}
public final int readFullyUntilEof(byte b[]) throws IOException {
return readFullyUntilEof(b, 0, b.length);
}
public final int readFullyUntilEof(byte b[], int off, int len) throws IOException {
if (len < 0)
throw new IndexOutOfBoundsException();
int n = 0;
while (n < len) {
int count = in.read(b, off + n, len - n);
if (count < 0)
break;
n += count;
}
return n;
}
}
我的最终代码现在看起来像这样:
new Thread(
new Runnable() {
@Override
public void run() {
try {
URI uri = URI.create("http://192.168.1.6:5000/api/tts");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("x-access-token", credentials.getAccessToken());
urlConnection.setRequestProperty("Accept", "*");
urlConnection.setChunkedStreamingMode(bufferSize);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.connect();
OutputStreamWriter osw = new OutputStreamWriter(urlConnection.getOutputStream());
String body = "{\"text\": \"" + text + "\", \"ttsLang\": \"" + language + "\"}";
Log.d("TTS_HTTP", body);
osw.write(body);
osw.flush();
osw.close();
Log.d("TTS_OUT", credentials.getAccessToken());
Log.d("TTS_OUT", urlConnection.getResponseCode() + " " + urlConnection.getResponseMessage());
// define the buffer size for audio track
int SAMPLE_RATE = 16000;
int bufferSize = AudioTrack.getMinBufferSize(SAMPLE_RATE, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT);
if (bufferSize == AudioTrack.ERROR || bufferSize == AudioTrack.ERROR_BAD_VALUE) {
bufferSize = SAMPLE_RATE * 2;
}
bufferSize *= 2;
TTSInputStream bis = new TTSInputStream(urlConnection.getInputStream());
AudioTrack audioTrack = new AudioTrack(
AudioManager.STREAM_MUSIC,
SAMPLE_RATE,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize * 2,
AudioTrack.MODE_STREAM);
byte[] buffer = new byte[bufferSize];
audioTrack.play();
int count;
while ((count = bis.readFullyUntilEof(buffer)) > 0) {
Log.d("TTS_COUNT", "Read " + count + " bytes.");
audioTrack.write(buffer, 0, buffer.length);
}
bis.close();
audioTrack.stop();
audioTrack.release();
} catch (IOException e) {
e.printStackTrace();
}
}
}
).start();
现在我的音频播放得很好,没有任何静电噪音。希望这对其他和我有同样问题的人有所帮助。
https://stackoverflow.com/questions/55995880
复制相似问题