2017-03-22 33 views
4

一些背景資料/ 2:POST流式音頻通過HTTP Android中

我想開發在Android應用程式語音相關的功能,使用戶可以使用語音搜索和服務器發送中間結果,而用戶說話(反過來更新UI)以及查詢完成時的最終結果。由於服務器只接受HTTP/2單套接字連接和Android HTTPUrlConnection doesn't support HTTP/2,我正在使用Retrofit2。

我已經看過thisthisthis但每個實施例中具有固定長度的數據,或者可以預先確定的尺寸...這對於音頻搜索的情況。

這裏就是我的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>。我試着用奧基奧以這種方式(來源: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的新手。如果我錯過了任何東西或部分代碼不清楚,請讓我知道,我會上傳該代碼段。謝謝。

回答

2

您可能可以使用Pipe從音頻線程生成數據並在網絡線程中使用它。

newly-created OkHttp recipe

/** 
* 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[]>或類似的事情。

+0

那麼基本上以生產者 - 消費者的方式解決它?可以使用okio完成嗎?如何使用一個POST將音頻數據追加到@Part(「audio」)RequestBody audio'中? – Papps

+0

Pipe類應該有所幫助。運行示例以查看控制流的外觀。 –

+0

與Pipe有同步問題。目前,它正在使用BlockingQueue 。 – Papps