0

I'm trying to implement a API method that streams a video file from a private Azure Storage Account to a video-html5 tag and it should allow me to forward/rewind in on the page. I have one method that just returns the entire file to the browser (which works) but doing so prevents me from forward/rewind the video so I'm trying to use PushStreamContent instead but it wont return the content to the browser, it only returns the metadata.

So my goals:

  • Stream video to browser (i.e. when having a a big file like 500mb i shouldnt have to wait for entire download)
  • Forward/Rewind/changing video time should work.

What am I missing here to get this to work?

    [HttpGet]
    [Route("api/video/{ext}/{filename}")]
    public async Task<HttpResponseMessage> ExecuteAsync(string filename, string ext)
    {
        
        var _filename = @"" + filename + "." + ext;

        string blobstorageconnection = _configuration.GetValue<string>("blobstorage");
        string blobContainer = _configuration.GetValue<string>("blobcontainer");

        CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(blobstorageconnection);
        CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
        CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(blobContainer);
        CloudBlockBlob blockBlob = cloudBlobContainer.GetBlockBlobReference(_filename);


        var response = new HttpResponseMessage();
        
        if (!blockBlob.Exists())
        {
            response.StatusCode = HttpStatusCode.NotFound;
            return response;
        }
        else
        {
            response.StatusCode = HttpStatusCode.OK;
        }


        response.Content = new PushStreamContent(async (outputStream, _, __) =>
        {
            try
            {
                
                await blockBlob.DownloadToStreamAsync(outputStream);
            }
            finally
            {
                outputStream.Close();
            }
        });


        response.Content.Headers.ContentType = new MediaTypeHeaderValue("video/" + ext);
        return response;

    }

This is my HTML code:

<section class="slice-lg sct-color-2 border-bottom" style="padding-top: 20px;">
    <div class="container col-11">
        <div class="row justify-content-center">
            <video width="640" controls autoplay="autoplay" preload="auto">
                <source src="/api/video/mp4/f0d67d82_mov_bbb" type="video/mp4">
            </video>
        </div>
    </div>
</section>

Output from my method:

{"version":{"major":1,"minor":1,"build":-1,"revision":-1,"majorRevision":-1,"minorRevision":-1},"content":{"headers":[{"Key":"Content-Type","Value":["video/mp4"]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"trailingHeaders":[],"requestMessage":null,"isSuccessStatusCode":true}
Daniel Björk
  • 2,475
  • 1
  • 19
  • 26

1 Answers1

0

If you use .Net Core is easier to work with FileStreamResult. if not then the best way is multipart here

[HttpGet]
[Route("stream")]
public IActionResult Stream(string id)
{
    var ext = "mp4";
    var contentType = $"video/{ext}";
    var fileName = $"{Guid.NewGuid()}.mp4";
    var stream = new FileStream("1.mp4", FileMode.Open, FileAccess.Read) ;
    if (stream == null)
        return NotFound($"{id}");

    var result = new FileStreamResult(stream, contentType ?? "application/octet-stream")
    {
        EnableRangeProcessing = true
    };
    result.FileDownloadName = fileName;

}
Stanislav
  • 459
  • 3
  • 6