【问题标题】:Incomplete video streaming to mobile browsers - HTTP headers不完整的视频流到移动浏览器 - HTTP 标头
【发布时间】:2016-12-03 05:28:07
【问题描述】:

我正在尝试使用 Nancy MVC 框架将 mp4(分段)视频流式传输到移动浏览器客户端。一切正常。附上代码。

问题是,视频将在流式传输的同时生成,因此 stream.Length 会随着时间的推移而增加。 有人知道如何支持这种情况吗?

(我尝试在“content-range”标头中提交长度,给出任意最大尺寸以包含整个视频大小,但无济于事......)

 /*called when /video is requested*/
Get["/video"] = _ => 
{
    if (Request.Headers.Keys.Contains("Range"))
      return Response.FromPartialStream(Request, File.OpenRead("../Page/video-fragmented.mp4"), "video/mp4");
    else
      /*from stream...*/
};

public static Response FromPartialStream(this IResponseFormatter f,
                                          Request req, Stream stream,
                                          string contentType)
{
    const string BYTES_RANGE_HEADER = "Range";

    if (req.Headers[BYTES_RANGE_HEADER].Count() != 1)
        throw new NotSupportedException();

    var rangeStr = req.Headers[BYTES_RANGE_HEADER].FirstOrDefault();
    var range = rangeStr.Replace("bytes=", String.Empty)
                        .Split(new string[] { "-" }, StringSplitOptions.RemoveEmptyEntries)
                        .Select(x => Int32.Parse(x))
                        .ToArray();

    var start = (range.Length > 0) ? range[0] : 0;
    var end = (range.Length > 1) ? range[1] : (int)(stream.Length - 1);

    var res = new PartialStreamResponse(stream, start, end, contentType)
                  .WithHeader("Connection", "keep-alive")
                  .WithHeader("Accept-Ranges", "bytes")
                  .WithHeader("Content-Range", "bytes " + start + "-" + end + "/" + stream.Length)
                  .WithHeader("Content-Length", (end - start + 1).ToString());

    Console.WriteLine("Requested range: {0}", rangeStr);
    return res;
}

public class PartialStreamResponse : Response
{
    Stream sourceStream = null;
    int start, end;

    public PartialStreamResponse(Stream sourceStream, int start, int end, string mimeType)
    {
        this.sourceStream = sourceStream;
        this.start = start;
        this.end = end;

        Contents = populateRequest;
        StatusCode = HttpStatusCode.PartialContent;
        ContentType = mimeType;
    }

    private void populateRequest(Stream stream)
    {
        Console.WriteLine("Begin stream...");
        sourceStream.CopyTo(stream, start, end);
        Console.WriteLine("End stream");
    }
}

编辑:提供此类文件也应该适用于移动浏览器(单个文件优于需要分段的 HLS 或 DASH)

【问题讨论】:

  • 您如何托管南希?这会影响解决方案。
  • 我使用自托管,但如果需要,我可以切换到 Nancy + IIS 或 AP.NET MVC + IIS。

标签: c# asp.net html video nancy


【解决方案1】:

至少 Chrome 和 Firefox 可以愉快地处理 200 OK 响应,而响应中没有 Content-Range 或 Content-Length 标头。在我看来,如果请求范围有一个有效的结束标记,你应该只回复206 Partial Content,否则只回复200 OK,没有内容长度并推送流。当然,另一件事是如何处理实时生成的文件。我建议将moov 部分放在一个单独的文件中,然后使用当前的moof 生成第二个文件——这样新客户最初会得到moov(应该是固定的)并且当该数据有已发送服务器将继续读取并提供moof 文件,该文件将被刷新。此外,为了避免 I/O 饥饿(服务器试图读取文件以及生成试图写入文件的内容),您至少可以拥有 2 个充当双缓冲区的 moof 文件 - 一个是最后完成的片段和另一个是当前正在编写的。

这是一个请求/响应标头在 Chrome 中工作的实时分段视频的示例:

在我看来,206 Partial Content 响应对于静态视频内容比对实时视频内容更有用,因为在这种情况下,浏览器可以获取 moov 原子,解析所有大小和偏移表,并在加载内容时提供搜索,这对于实时视频是不可能的。

【讨论】:

  • 非常感谢!一旦我检查它就会接受(这个东西也必须在移动浏览器上工作......)。
  • 很遗憾,它不适用于移动浏览器。
  • 好吧,iOS 根本不支持 fMP4(在上一次 WDDC 中他们宣布将支持它),而且 Chrome 似乎很挑剔(afaik Chrome 对或smth like that before the actual data and requires some special atom),但这就是目前的情况——没有万无一失的解决方案。
  • @dajuric 恐怕你无法用一条管道处理所有客户。我会说你仍然必须拥有 HLS + MP4。
【解决方案2】:

使用多个请求(每个片段一个)或使用分块传输。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-29
    • 1970-01-01
    • 2017-10-08
    • 2016-01-30
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多