Search code examples
c#resthttpclientpushstreamcontent

Sending live audio file to REST server using HttpClient and PushStreamContent


I need to stream audio data from the microphone to a REST server.

I am working with a propriatery ASR engine and need to collect the data then stream it in real time in a single call to PostAsync Looking online, I found articles on PushStreamContent but either I am not using it correctly I don't understand what I'm doing (or both).

I have a MemoryStream called stream_memory to which I write data constantly from the main thread and I want to read it, while data is streaming, and post it in real time in a single post. In the example below, I also use an event stream_data_event and an object lock to prevent multiple threads writing to the MemoryStream at the same time. I clear the memory stream every time I read from it as I don't need the data afterwards.

Here is a snip of my code that is running in a thread of its own:

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();

The call to PostAsync calls the code for the PushStreamContent as expected. However, as long as I am in the while loop, nothing is sent to the server (checked on wireshark). If I exit the loop manually in debugger and call close on the stream, PostAsync exists but nothing is sent to the server.

I need to have a way to continue streaming information while in the PostAsync and have the data go out as the audio arrives.

Any ideas?


Solution

  • It turns out that the reason nothing was sent to the server has to do with the way wireshark displays HTTP results. My expectations were that once the request was sent I would see it immediately in wireshark. However, wireshark only shows the request once it is complete which means it is shown far after the request started streaming.

    After I realized that, I could see by data being sent over to the server.