How to stream video with interval request?

Asked

Viewed 70 times

5

I have a video saved in the database with type VARBINARY(MAX).

How can I make a request range ?

The following code gets the full video from the database and plays in the variable video_byte; This is a problem for big video, to avoid this I need to mount range requests. Follow the following code as I am doing now:

public async Task<IActionResult> GetStreamVideo()
{    
    var result = await _context.Files
        .Where(x => x.Id == 1)
        .SingleOrDefaultAsync();

    byte[] video_byte = result.Video;    
    if (video_byte == null)
    {
        return BadRequest();
    }
    return File(video_byte, "video/mp4");
}

How can I get piece by piece into Asp.net core ?

The following code works very well on the standard Asp.net mvc (no core), and I also use the library: https://github.com/tpeczek/Lib.Web.Mvc

[HttpGet]
public ActionResult GetStreamVideo()
{
    byte[] test = null;
    DateTime lastModificationDate = DateTime.MinValue;

    using (var ctx = new Entities())
    {
        var result = ctx.Files.Where(x => x.Id == 1).SingleOrDefault();

        test = result.Video;
        lastModificationDate = result.LastModificationDate;
    }

    return new RangeFileContentResult(test, "video/mp4", "Name.mp4", lastModificationDate);
}
  • 1

    I have an example here that may be useful to you. I adapted another example that is documented in my code. I won’t be able to answer right now, but if you say it’s useful I can try to adapt something to your scenario if there are differences.

  • @Georgewurthmann I’ll look at the link, thank you.

  • @Georgewurthmann I looked in your code, in the line where you have SingleOrDefault(); will not get the full video ?

  • On this line he is not taking the file, only the record in the comic referring to the video. In this record has the path where the file is stored the file it reads a little lower in 'fileInfo' and this file is returned in ranges for streaming, this is what it needs?

  • @Georgewurthmann That’s right! The idea is not to get the full video, but piece by piece. Because in my code it is returning full byte_array from the database. select takes about 20 seconds. This is a problem.

  • I understood Matheus, but my example does not get around this problem, my file is not saved in BD... in the example BD stores only his physical path for after it is loaded, which is the BD used?

  • @Georgewurthmann MS Sql Server 17

Show 3 more comments

1 answer

2

This can be done by consulting the order headers. More specifically the header Range. Then you can use ByteRangeStreamContent to return only a portion of the video. In terms of database you can do nothing basically, since it is not possible to know where is the portion of the video you are looking for deterministically, at least not in a simple way.

var range = Request.Headers.Range?.Ranges?.FirstOrDefault();
if (range != null)
{
    var stream = File.Open(record.FilePath, FileMode.Open,
        FileAccess.Read, FileShare.Read);
    var response = Request.CreateResponse(HttpStatusCode.PartialContent);
    response.Content = new ByteRangeStreamContent(stream, new RangeHeaderValue(range.From, range.To), "audio/mp3");
    return ResponseMessage(response);
}
else
{
    var stream = File.Open(record.FilePath, FileMode.Open,
        FileAccess.Read, FileShare.Read);
    var response = Request.CreateResponse(HttpStatusCode.OK);
    response.Content = new StreamContent(stream);
    return ResponseMessage(response);
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.