Dear Android advanced dev :)
I would like to dev an App which record audio from microphone and send registered data to a Speech To Text web service, in real-time transcription mode.
So i need to make a HTTP request and keep this request to continuously send audio data and retrieve , in parallel, the transcription result.
I'm really able to work with the API with a tool like curl
but I'm really disappointed not to be able to do it in Java.
You can find a summary of what I try to do in a class. I'm trying to use HttpUrlConnection, I don't know if this is the right approach.
My problem is the following: I can send the audio as it is recorded, however, as soon as I activate the readInputStream
method to read the response in parallel, the connection is closed.
The header of the response contains Transfer-Encoding: chunked
.
Is there a better way to do this?
Thank you.
/* list of import hidden */
public class RecordAndStream {
int SAMPLE_RATE = 8000;
boolean record;
URL url;
HttpURLConnection httpURLConnection;
InputStreamReader inputStreamReader;
OutputStream outputStream;
public void readInputStream() {
try {
InputStream inputStream = null;
inputStream = new BufferedInputStream(this.httpURLConnection.getInputStream());
this.inputStreamReader = new InputStreamReader(inputStream);
int data = 0;
data = this.inputStreamReader.read();
String xml_result = "";
while (data != -1) {
xml_result += String.valueOf((char) data);
data = this.inputStreamReader.read();
}
Log.d("LOG", "inputStreamReader=\n" + xml_result);
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendAudioStream() {
int bufferSize = AudioRecord.getMinBufferSize(this.SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT);
@SuppressLint("MissingPermission")
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.DEFAULT,
this.SAMPLE_RATE,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
audioRecord.startRecording();
short[] audioBuffer = new short[8192];
while (this.record) {
int numberOfShort = audioRecord.read(audioBuffer, 0, audioBuffer.length);
ByteBuffer bfSTT = ByteBuffer.allocate(numberOfShort * 2);
bfSTT.order(ByteOrder.LITTLE_ENDIAN);
for (int z = 0; z < numberOfShort; z++) {
bfSTT.putShort(audioBuffer[z]);
}
try {
this.outputStream.write(bfSTT.array());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
this.outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
audioRecord.stop();
audioRecord.release();
this.httpURLConnection.disconnect();
}
public void stopRecord() {
this.record = false;
}
public void startRecord() {
this.record = true;
// declaration d'une url
try {
this.url = new URL("https://sercice_url_to_call");
} catch (MalformedURLException e) {
Log.e("LOG", "MalformedURLException");
}
this.httpURLConnection = null;
try {
this.httpURLConnection = (HttpURLConnection) this.url.openConnection();
this.httpURLConnection.setRequestProperty("Authorization", "Basic " + Base64.encodeToString("xxx:YYY".getBytes(), Base64.NO_WRAP));
this.httpURLConnection.setUseCaches(false);
this.httpURLConnection.setRequestMethod("POST");
this.httpURLConnection.setRequestProperty("Content-Type", "");
this.httpURLConnection.setRequestProperty("Accept", "*/*");
this.httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
this.httpURLConnection.setRequestProperty("Transfer-Encoding", "chunked");
this.httpURLConnection.setRequestProperty("Expect", "100-continue");
this.httpURLConnection.setRequestProperty("Accept-Encoding", "gzip");
} catch (ProtocolException e) {
Log.e("LOG", "ProtocolException");
} catch (IOException e) {
Log.e("LOG", "IOException");
}
try {
//to tell the connection object that we will be wrting some data on the server and then will fetch the output result
//this.httpURLConnection.setDoOutput(true);
this.httpURLConnection.setDoOutput(true);
this.httpURLConnection.setDoInput(true);
// this is used for just in case we don't know about the data size associated with our request
this.httpURLConnection.setChunkedStreamingMode(8192);
// to write tha data in our request
this.outputStream = new BufferedOutputStream(this.httpURLConnection.getOutputStream());
// to read the data in the response
new Thread((new Runnable() {
protected RecordAndStream ref;
public Runnable init(RecordAndStream ref) {
this.ref = ref;
return this;
}
@Override
public void run() {
this.ref.readInputStream();
}
}).init(this)).start();
sendAudioStream();
} catch (Exception e) {
e.printStackTrace();
}
}
}
After testing several solutions like OkHttp or HttpClient from the Apache foundation, I didn't find any off the shelf solution. So I managed myself the http layer directly in the Buffer of a simple Socket. It works perfectly, I send in stream while receiving in stream.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.