首页 > 解决方案 > C# 核心 HTML5 视频不会在带有范围标签的 chrome 中加载

问题描述

我们目前正在开发一个通过 HTML5 标签加载视频的简单 HTML 页面。在后端,我们有一个 webapi 端点,它返回带有“Accept-Ranges: bytes”标头的视频(或视频块)。

Chrome 似乎对端点进行了两次调用,一次调用 bytes:0- 一次调用 bytes:10452992-

视频是 MP4 和 10498677 字节长。

但是,视频不会播放,只是加载为黑屏。

我们的端点如下所示:

 public async Task<IActionResult> StreamVideoWithToken(string token, long id)

要获取起始字节位置,我们使用:

var range = Request.Headers["Range"].First();
var rangeType = range.Split('=');
if (rangeType[0] == "bytes")
{
    var firstLast = rangeType[1].Split('-');
    long first = 0;
    if (firstLast.Length > 0 && firstLast[0] != "")
        if (!long.TryParse(firstLast[0], out first)) first = 0;

    long last = 0;
    if (firstLast.Length > 1)
        if (!long.TryParse(firstLast[1], out last)) last = 0;

    byteRange.start = first;
    byteRange.end = last;
}

这将获取起始字节。

然后我们从服务器获取流并将其作为响应传回。

// Returns a stream of only the required bytes (start to EOF)
var fs = _assetService.GetContentStream(asset.Id, byteRange.start);

fs.Seek(0, SeekOrigin.Begin);

Response.ContentLength = byteRange.start + s.fetchedLength;

if (byteRange.start > 0)
{
    Response.StatusCode = (int)HttpStatusCode.PartialContent;
    Response.Headers.Add("Content-Range", byteRange.start + "-" + (byteRange.start + s.fetchedLength));
}

return new FileStreamResult(fs, "video/mp4")~;

如果我们关闭“Accept-Ranges: bytes”标头,它会对完整视频发出一个请求,该视频成功播放,但无法导航到任何特定时间。

请求如下所示:

GET: https://localhost:44392/api/asset/StreamVideo/xxx/1261

Accept-Encoding: identity;q=1, *;q=0
Range: bytes=10452992-
Referer: http://localhost:4200/catalogue/a/1261
Sec-Fetch-Mode: no-cors

响应如下所示:

Status Code: 206 (Partial Content)

accept-ranges: bytes
access-control-allow-credentials: true
access-control-allow-headers: Authorization, Content-Type, x-auth-token
access-control-allow-origin: *
access-control-expose-headers: X-Error-Message
content-length: 45685
content-range: 10452992-10498677
content-type: video/mp4
date: Sun, 22 Sep 2019 14:49:14 GMT
server: Kestrel
status: 206
x-powered-by: ASP.NET
x-sourcefiles: xxx

标签: c#.net-corehtml5-video

解决方案


您的实现存在几个问题(请发布完整的代码,使用这些代码段无法理解s您正在使用的内容s.Item2):

  1. fs.Seek(0, SeekOrigin.Begin);- 要么这是一个错字,要么你不明白范围标题是如何工作的。您必须寻找指定为范围开始的偏移量,并且只提供到范围的结束。
  2. 在处理范围值时,如果未提供,则当前保留last为 0,但请记住,在这种情况下,您仍然需要提供从文件开头到结尾的内容。
  3. 为了玩得好,您还应该在响应中设置Content-Range标头,因为您正在回复 206。

编辑: 如果您使用FileResult而不是FileStreamResult它将处理Range标头本身,请注意 2.1 中的行为更改 - 低于 2.1 类会自动进行处理,因为 2.1 您需要启用EnableRangeProcessing属性FileResult才能进行处理。


推荐阅读