繁体   English   中英

在Android中通过HTTP / 2进行POST流音频

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM