5

Streaming works well in all browsers except Safari. As I know request should support range header.

Here is the code that I am using:

    public async Task<FileStreamResult> GetVideoStream()
        {
            if (Request.Headers.ContainsKey("Range"))
            {
                Request.Headers.TryGetValue("Range", out var range);
                _httpClient.DefaultRequestHeaders.Add("Range", range.ToString());
            }

            var stream = await _httpClient.GetStreamAsync(_url);

            return File(stream, "video/mp4", true);
        }

Request:

curl --range 0-99 https://localhost:44312/GetVideoStream -o D:\test

is working good and saves only 100bytes to file.

Have trying also variations of controls muted playsinline preload="metadata" and type="video/mp4"

Alexej Sommer
  • 2,677
  • 1
  • 14
  • 25

2 Answers2

3

i think For a legit "Range" response, your need to return status code "206 partial Content"

let's try:

public async Task<FileStreamResult> GetVideoStream()
        {
            if (Request.Headers.ContainsKey("Range"))
            {
                Request.Headers.TryGetValue("Range", out var range);
                _httpClient.DefaultRequestHeaders.Add("Range", range.ToString());
            }

            var stream = await _httpClient.GetStreamAsync(_url);

           HttpContext.Response.StatusCode = 206;

            return File(stream, "video/mp4", true);
        }
foad abdollahi
  • 1,733
  • 14
  • 32
  • Thank you, @foadabd! I have tried different variations with returning 206 status code, but also without result. In this particular case if File is returned it should return 206 in case if Range header appears in the request – Alexej Sommer Jul 13 '20 at 08:46
1

Finally, I was able to force Safari stream videos. It was required to set "Content-Range" header:

public async Task<FileStreamResult> GetVideoStream()
{
  if (Request.Headers.ContainsKey("Range"))
  {
      _httpClient.DefaultRequestHeaders.Remove("Range");
      var headersResponse = await _httpClient.GetAsync(_url, HttpCompletionOption.ResponseHeadersRead);

      Request.Headers.TryGetValue("Range", out var range);

      if (headersResponse.IsSuccessStatusCode && headersResponse.Content.Headers.GetValues("Content-Length").Any())
          HttpContext.Response.Headers.Add("Content-Range", $"{range[0].Replace("=", " ")}/{headersResponse.Content.Headers.GetValues("Content-Length").First()}");

      _httpClient.DefaultRequestHeaders.Add("Range", range.ToString());
  }

  var stream = await _httpClient.GetStreamAsync(_url);

  return File(stream, "video/mp4", true);
}
Alexej Sommer
  • 2,677
  • 1
  • 14
  • 25