[英]POST Streaming Audio over HTTP/2 in Android
一些背景:
我正在嘗試在android應用程序上開發與語音相關的功能,用戶可以在其中使用語音進行搜索,並且服務器會在用戶講話時發送中間結果(依次更新UI),並在查詢完成后發送最終結果。 由於服務器僅接受HTTP / 2單套接字連接,而Android HTTPUrlConnection 尚不支持 HTTP / 2,因此我正在使用Retrofit2。
我已經看過了這個 , 這個和這個,但是每個示例都有固定長度的數據,或者可以事先確定大小……對於音頻搜索而言,情況並非如此。
這是我的POST方法:
public interface Service{
@Streaming
@Multipart
@POST("/api/1.0/voice/audio")
Call<ResponseBody> post(
@Part("configuration") RequestBody configuration,
@Part ("audio") RequestBody audio);
}
該方法以以下方式發送配置文件(包含音頻參數-JSON結構)和流音頻。 (預期的POST請求)
Content-Type = multipart/form-data;boundary=----------------------------41464684449247792368259
//HEADERS
----------------------------414646844492477923682591
Content-Type: application/json; charset=utf-8
Content-Disposition: form-data; name="configuration"
//JSON data structure with different audio parameters.
----------------------------414646844492477923682591
Content-Type: audio/wav; charset=utf-8
Content-Disposition: form-data; name="audio"
<audio_data>
----------------------------414646844492477923682591--
不太確定如何發送流(!!) <audio_data>
。 我嘗試使用Okio以這種方式為音頻創建多部分(來自: https : //github.com/square/okhttp/wiki/Recipes#post-streaming )
public RequestBody createPartForAudio(final byte[] samples){
RequestBody requestBody = new RequestBody() {
@Override
public MediaType contentType() {
return MediaType.parse("audio/wav; charset=utf-8");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
//Source source = null;
sink.write(samples);
}
};
return requestBody;
}
這當然沒有用。 這是繼續將音頻樣本寫入ResponseBody的正確方法嗎? 我到底應該在哪里調用Service.post(config, audio)
方法,這樣我就不會在每次音頻緩沖區中有東西時都結束發布配置文件。
另外,由於必須繼續發送流音頻,因此如何保持相同的POST連接保持打開狀態,直到用戶停止講話才將其關閉?
我基本上是OkHttp和Okio的新手。 如果我錯過了任何內容或部分代碼不清楚,請讓我知道,我將上傳該代碼段。 謝謝。
您也許可以使用Pipe從音頻線程中產生數據並在網絡線程中使用它。
通過新創建的OkHttp配方 :
/**
* This request body makes it possible for another
* thread to stream data to the uploading request.
* This is potentially useful for posting live event
* streams like video capture. Callers should write
* to {@code sink()} and close it to complete the post.
*/
static final class PipeBody extends RequestBody {
private final Pipe pipe = new Pipe(8192);
private final BufferedSink sink = Okio.buffer(pipe.sink());
public BufferedSink sink() {
return sink;
}
@Override public MediaType contentType() {
...
}
@Override public void writeTo(BufferedSink sink) throws IOException {
sink.writeAll(pipe.source());
}
}
如果您的數據可以連續寫入,則此方法最有效。 如果不能,那么最好用BlockingQueue<byte[]>
或類似的方法做些類似的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.