使用 HttpClient 和 PushStreamContent 将实时音频文件发送到 REST 服务器
Sending live audio file to REST server using HttpClient and PushStreamContent
我需要将音频数据从麦克风流式传输到 REST 服务器。
我正在使用专有的 ASR 引擎,需要收集数据然后在对 PostAsync 的单次调用中实时流式传输
在网上查找,我找到了有关 PushStreamContent 的文章,但要么我没有正确使用它,要么我不明白我在做什么(或两者都不知道)。
我有一个名为 stream_memory 的 MemoryStream,我不断地从主线程向其写入数据,我想在数据流式传输时读取它,并且 post post。在下面的示例中,我还使用事件 stream_data_event 和对象锁来防止多个线程同时写入 MemoryStream。我每次读取内存流时都会清除内存流,因为之后我不需要数据。
这是我的代码片段 运行 在它自己的线程中:
http_client = new HttpClient();
http_client.http_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
http_client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", "en-us");
http_client.DefaultRequestHeaders.TransferEncodingChunked = true;
HttpContent content = new System.Net.Http.PushStreamContent(async (stream, httpContent, transportContext) =>
{
while (stream_data_event.WaitOne())
{
lock (main_window.stream_memory_lock)
{
stream_data_event.Reset();
long write_position = main_window.stream_memory.Position;
main_window.stream_memory.Seek(0, SeekOrigin.Begin);
main_window.stream_memory.CopyTo(stream, (int)write_position);
main_window.stream_memory.Position = 0;
}
}
});
content.Headers.TryAddWithoutValidation("Content-Type", "audio/L16;rate=8000");
string request_uri = String.Format("/v1/speech:recognize");
HttpResponseMessage response = await http_client.PostAsync(request_uri, content);
string http_result = await response.Content.ReadAsStringAsync();
对 PostAsync 的调用按预期调用了 PushStreamContent 的代码。
但是,只要我在 while 循环中,就不会向服务器发送任何内容(在 wireshark 上检查过)。
如果我在调试器中手动退出循环并在流上调用关闭,则 PostAsync 存在但没有任何内容发送到服务器。
我需要有一种方法可以在 PostAsync 中继续流式传输信息,并在音频到达时输出数据。
有什么想法吗?
事实证明,没有向服务器发送任何内容的原因与 wireshark 显示 HTTP 结果的方式有关。
我的期望是一旦请求被发送,我会立即在 wireshark 中看到它。但是,wireshark 仅在请求完成后才显示请求,这意味着它会在请求开始流式传输之后很久才显示。
意识到这一点后,我可以看到发送到服务器的数据。
我需要将音频数据从麦克风流式传输到 REST 服务器。
我正在使用专有的 ASR 引擎,需要收集数据然后在对 PostAsync 的单次调用中实时流式传输 在网上查找,我找到了有关 PushStreamContent 的文章,但要么我没有正确使用它,要么我不明白我在做什么(或两者都不知道)。
我有一个名为 stream_memory 的 MemoryStream,我不断地从主线程向其写入数据,我想在数据流式传输时读取它,并且 post post。在下面的示例中,我还使用事件 stream_data_event 和对象锁来防止多个线程同时写入 MemoryStream。我每次读取内存流时都会清除内存流,因为之后我不需要数据。
这是我的代码片段 运行 在它自己的线程中:
http_client = new HttpClient();
http_client.http_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
http_client.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", "en-us");
http_client.DefaultRequestHeaders.TransferEncodingChunked = true;
HttpContent content = new System.Net.Http.PushStreamContent(async (stream, httpContent, transportContext) =>
{
while (stream_data_event.WaitOne())
{
lock (main_window.stream_memory_lock)
{
stream_data_event.Reset();
long write_position = main_window.stream_memory.Position;
main_window.stream_memory.Seek(0, SeekOrigin.Begin);
main_window.stream_memory.CopyTo(stream, (int)write_position);
main_window.stream_memory.Position = 0;
}
}
});
content.Headers.TryAddWithoutValidation("Content-Type", "audio/L16;rate=8000");
string request_uri = String.Format("/v1/speech:recognize");
HttpResponseMessage response = await http_client.PostAsync(request_uri, content);
string http_result = await response.Content.ReadAsStringAsync();
对 PostAsync 的调用按预期调用了 PushStreamContent 的代码。 但是,只要我在 while 循环中,就不会向服务器发送任何内容(在 wireshark 上检查过)。 如果我在调试器中手动退出循环并在流上调用关闭,则 PostAsync 存在但没有任何内容发送到服务器。
我需要有一种方法可以在 PostAsync 中继续流式传输信息,并在音频到达时输出数据。
有什么想法吗?
事实证明,没有向服务器发送任何内容的原因与 wireshark 显示 HTTP 结果的方式有关。 我的期望是一旦请求被发送,我会立即在 wireshark 中看到它。但是,wireshark 仅在请求完成后才显示请求,这意味着它会在请求开始流式传输之后很久才显示。
意识到这一点后,我可以看到发送到服务器的数据。