Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Core 2.0 Web API for Video Streaming from FileStream

I have found a bunch of examples that use objects not available to me within my application and don't seem to match up to my version of .NET Core web API. In essence I am working on a project that will have <video> tags on a web page and want to load the videos using a stream from the server rather than directly serving the files via a path. One reason is the source of the files may change and serving them via path isn't what my customer wants. So I need to be able to open a stream and async write the video file.

This for some reason produces JSON data so that's wrong. But I just don't understand what I need to do to send a streamed video file to a <video> tag in HTML.

Current Code:

[HttpGet]
public HttpResponseMessage GetVideoContent()
{
    if (Program.TryOpenFile("BigBuckBunny.mp4", FileMode.Open, out FileStream fs))
    {
        using (var file = fs)
        {
            var range = Request.Headers.GetCommaSeparatedValues("Range").FirstOrDefault();
            if (range != null)
            {
                var msg = new HttpResponseMessage(HttpStatusCode.PartialContent);
                var body = GetRange(file, range);
                msg.Content = new StreamContent(body);
                msg.Content.Headers.Add("Content-Type", "video/mp4");
                //msg.Content.Headers.Add("Content-Range", $"0-0/{fs.Length}");
                return msg;
            }
            else
            {
                var msg = new HttpResponseMessage(HttpStatusCode.OK);
                msg.Content = new StreamContent(file);
                msg.Content.Headers.Add("Content-Type", "video/mp4");
                return msg;
            }
        }
    }
    else
    {
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }
}
like image 463
Bailey Miller Avatar asked Apr 02 '18 21:04

Bailey Miller


1 Answers

HttpResponseMessage is not used as a return type in asp.net-core it will read that as an object model and serialize it in the response by design, as you have already observed.

Luckily in ASP.NET Core 2.0, you have

Enhanced HTTP header support

If an application visitor requests content with a Range Request header, ASP.NET will recognize that and handle that header. If the requested content can be partially delivered, ASP.NET will appropriately skip and return just the requested set of bytes. You don't need to write any special handlers into your methods to adapt or handle this feature; it's automatically handled for you.

So now all you have to do is return the file stream

[HttpGet]
public IActionResult GetVideoContent() {
    if (Program.TryOpenFile("BigBuckBunny.mp4", FileMode.Open, out FileStream fs)) {        
        FileStreamResult result = File(
            fileStream: fs, 
            contentType: new MediaTypeHeaderValue("video/mp4").MediaType, 
            enableRangeProcessing: true //<-- enable range requests processing
        );
        return result;
    }
     
    return BadRequest();
}

Making sure to enable range requests processing. Though, as stated in the documentation, that should be handled based on the request headers and whether that data can be partially delivered.

From there it is now a simple matter of pointing to the endpoint from the video client and let it do its magic

like image 131
Nkosi Avatar answered Sep 18 '22 12:09

Nkosi