I'm building an API in .NET 8 that when called, will connect to an IP camera in the backend and stream the content (mjpeg) to the client's browser.
I'm not sure how to properly do this, but I got my code below to work on Kestrel/Visual Studio.
However, when I host my app on IIS 10, things get weird. The client will connect to the server, but the video will not show.
Using DevTools I can see that the request will freeze in the "Downloading from Server" state. If I manually kill the connection to the IP Camera in the backend, the browser will quickly show a few frames from the stream and the request will complete.
In addition to this code, I've tried reading the IP Camera stream into a buffer and then writing it out to the response body. However, it only works on Kestrel and not on IIS. I'm wondering if I need to configure something on IIS? I've been working on this for a couple weeks and I'm out of ideas.
Server Side
public async Task<Stream> Video()
{
AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false);
string baseAddress = "http://192.168.1.100";
string clientId = "Username";
string clientSecret = "Password";
var credCache = new CredentialCache
{
{ new Uri(baseAddress), "Digest", new NetworkCredential(clientId, clientSecret) }
};
HttpClient httpClient = new HttpClient(new HttpClientHandler { Credentials = credCache });
httpClient.BaseAddress = new Uri(baseAddress);
var response = await httpClient.GetStreamAsync("/cgi-bin/mjpg/video.cgi?channel=1&subtype=1");
HttpContext.Response.Headers.ContentType = "multipart/x-mixed-replace; boundary=--myboundary";
return response;
}
HTML
<div class="col-md-4">
<img height="480" width="640" src="/Video">
</div>
I faced the same issue and it was fixed when I disabled the response body buffering:
var responseBodyFeature = context.Features.Get<IHttpResponseBodyFeature>();
if (responseBodyFeature != null) responseBodyFeature.DisableBuffering();
Also note that your boundary value should not start with double hyphens when you define it in your header, so it should look like this:
"multipart/x-mixed-replace; boundary=myboundary"