【问题标题】:C# core HTML5 video won't load in chrome with range tagsC# 核心 HTML5 视频不会在带有范围标签的 chrome 中加载
【发布时间】:2020-01-22 19:29:16
【问题描述】:

我们目前正在开发一个通过 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-core html5-video


    【解决方案1】:

    您的实现存在几个问题(请发布完整代码,使用这些 sn-ps 无法理解 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 您需要启用@987654330 FileResult 的 @ 属性用于进行处理。

    【讨论】:

    • 1.fs.seek - 我只检索我想要返回的文件部分,所以我必须从流的开头开始(所以,如果它们从字节 9000 开始10000 个文件,我的流只有 1000 字节长) 2. 如果 last 为 0(实际上,如果 last 是任何东西),我总是从头到尾返回 3. 我添加了 content-range 标头,但没有区别。请参阅上面的修改以了解更改的响应。
    • 我还将 s.Item2 - 重命名为 s.fetchedLength - 这是检索到的内容的长度(如果他们要求范围为 9000-end,则为 1000 个字节)
    • “我只检索我想要返回的文件部分” - 您发布的代码在哪里可见?您只需寻找第一个字节。
    • 添加了返回从服务器请求的文件部分的代码行(这些不是驱动器上的文件,而是包含在资产管理器中,因此我们可以检索部分内容。 GetContentStream(asset.Id, byteRange.start); 从“请求的开始”返回到 EOF
    • @TrevorWatson,好的,现在至少 Seek 有意义。另一件看起来很奇怪的事情是你的内容长度是一个范围 - 你的范围是 10452992-10498677,所以内容长度应该是 10498677-10452992+1=45686。此外,也许可以按照此链接格式化标题developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range:&lt;start&gt;-&lt;end&gt;/&lt;size&gt;。如果这些都没有帮助,那么请将一个有效的 URL 粘贴到该系统,以便我们可以使用 ffmpeg 或类似的东西对其进行测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 2011-01-26
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多