Asp.net core 8 , IIS and Video Streaming, Low level

Kishor Pise 1 Reputation point
2024-05-31T23:24:02.0133333+00:00

Hello All,

Have simple sample web api application, coded in .net core 8, deployed on kestrel and IIS, a typical scenario. I have created one end point that streams local video file. File is about 400 MB and approx. 4 mins in length. Below code works.

 [HttpGet]
 [Route("videoF")]
 public IActionResult StreamVideo()
 {

     var cancellationToken = HttpContext.RequestAborted;

     // Set a timeout of 30 seconds
     var timeout = TimeSpan.FromSeconds(30);
     var cts = new CancellationTokenSource(timeout);
     var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cts.Token).Token;

     if (!System.IO.File.Exists(_mp4FilePath))
     {
         return NotFound();
     }

     var stream = new FileStream(_mp4FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
     return File(stream, "video/mp4"    );
 }

 

Interesting point is, when Url is hit directly in chrome, video plays, but stops after 40-50 seconds. time is not fixed. Not sure if below code makes any difference, so deployed on IIS as well. Same error occured.

 

 

 

builder.WebHost.ConfigureKestrel(serverOptions => { serverOptions.Limits.MaxRequestBodySize = 100428800; });

Now In developer tools, if chrome, I can see multiple video requests for same video file while playing and data is getting download up to 500 MB per request. 3-8 request I can see, but after stopping there is no data download.

Second point - Video is displayed only in chrome. In IE it opens up media player and does not play video. VlC also unable to play any stream. Is there any sure shot low level API available to address connection issue and handle quality for stored video files ?

There is another endpoint written, This downloads video but it does not play in chrome. I can see data download in developer studio.

 

 

           public async Task<ActionResult> VideoMedia()
  {
      try
      {
          var fileInfo = new FileInfo(_mp4FilePath);
          // Open the file stream
          using var stream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true);
          // Set timeout duration (adjust as needed)
          var timeout = TimeSpan.FromSeconds(1000);
          var timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
          var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(HttpContext.RequestAborted, timeoutCancellationTokenSource.Token).Token;
          // Set the content type
          HttpContext.Response.ContentType = "video/mp4";
          // Start streaming the file
          while (!linkedToken.IsCancellationRequested)
          {
              var buffer = new byte[4096]; // Adjust buffer size as needed
              var bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, linkedToken);                   
              // Write the data to the response stream
              await HttpContext.Response.Body.WriteAsync(buffer, 0, bytesRead, linkedToken );
              await HttpContext.Response.Body.FlushAsync(linkedToken );
          }
          return new EmptyResult(); // Stream completed successfully
      }
      catch (OperationCanceledException)
      {
          // Handle timeout or client disconnection
          return StatusCode(500, "Streaming aborted due to timeout or client disconnection.");
      }
      catch (Exception ex)
      {
          // Handle other exceptions
          return StatusCode(500, $"An error occurred: {ex.Message}");
      }
  }


 

 

Experts comments are appreciated. Please note, This is ,net core 8. 

 

Thanks and regards.

 

 

 

 

Developer technologies | ASP.NET | ASP.NET Core
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2024-06-01T16:31:57.0366667+00:00

    To support stop/play most video streaming clients use range requests. That is they request a range of bytes of the video file, so it may file requests rather than one. Just use one of the file overloads that support range requests.

    https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.http.results.file?view=aspnetcore-8.0


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.