简体   繁体   English

ASP.Net Core Web Api 中的异步视频流不起作用

[英]Async video streaming in ASP.Net Core Web Api is not working

I have used http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/ this technique before and worked perfect for async video streaming.我之前使用过http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/这种技术,非常适合异步视频流。

But for ASP.NET Core this way is not working as expected.但是对于 ASP.NET Core,这种方式无法按预期工作。

By Video streaming class is:按视频流类是:

public class VideoStream
{
    private readonly string _filename;
    public VideoStream(string filename)
    {
        _filename = filename;
    }

    public async Task WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
    {
        try
        {
            var buffer = new byte[65536];
            using (var video = File.Open(_filename, FileMode.Open, FileAccess.Read))
            {
                var length = (int)video.Length;
                var bytesRead = 1;
                while (length > 0 && bytesRead > 0)
                {
                    bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length));
                    await outputStream.WriteAsync(buffer, 0, bytesRead);
                    length -= bytesRead;
                }
            }
        }
        catch (Exception)
        { return; }
        finally
        {
            outputStream.Flush();
            outputStream.Dispose();
        }
    }
}

and I have the following Action for video streaming requests:我对视频流请求有以下操作:

    [HttpGet]
    [Route("[action]")]
    public IActionResult GetVideo(int id)
    {
        var fileName = GetVideoFileName(id);
        var video = new VideoStream(fileName);
        var response = new HttpResponseMessage
        {
            Content = new PushStreamContent(video.WriteToStream, new MediaTypeHeaderValue("video/mp4"))
        };
        var objectResult = new ObjectResult(response);
        objectResult.ContentTypes.Add(new Microsoft.Net.Http.Headers.MediaTypeHeaderValue("video/mp4"));
        return objectResult;
    }

Since by default Asp.Net Core doesn't have built-in Media Formatter for video/mp4 I have created the following custom Media Formatter由于默认情况下 Asp.Net Core 没有用于视频/mp4 的内置媒体格式化程序,因此我创建了以下自定义媒体格式化程序

 public class VideoOutputFormatter : IOutputFormatter
{
    public bool CanWriteResult(OutputFormatterCanWriteContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));
            return true;
    }
    public async Task WriteAsync(OutputFormatterWriteContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));
        var response = context.HttpContext.Response;
        response.ContentType = "video/mp4";

       How to impelemnt  ???
    }
}

and added the following line to Startup.cs并将以下行添加到 Startup.cs

 services.AddMvc(options =>
        {
              options.OutputFormatters.Add(new VideoOutputFormatter());
        });

It actually calls my custom formatter.它实际上调用了我的自定义格式化程序。 I doesn't know how to implement this custom media formatter for video/mp4.我不知道如何为视频/mp4 实现这个自定义媒体格式化程序。 Anyone can help me ?任何人都可以帮助我吗?

Looking at the source code for Asp.NET Core really helped me find the answer to this one.查看 Asp.NET Core 的源代码确实帮助我找到了这个问题的答案。 They have a StreamOutputFormatter class that's really close to what you want to use.他们有一个StreamOutputFormatter类,它非常接近您想要使用的内容。 I only had to modify it to look for PushStreamContent and it worked like a charm.我只需要修改它来寻找PushStreamContent ,它就像一个魅力。

Here's my complete VideoOutputFormatter:这是我完整的 VideoOutputFormatter:

public class VideoOutputFormatter : IOutputFormatter
{
    public bool CanWriteResult(OutputFormatterCanWriteContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        if (context.Object is PushStreamContent)
            return true;

        return false;
    }

    public async Task WriteAsync(OutputFormatterWriteContext context)
    {
        if (context == null)
            throw new ArgumentNullException(nameof(context));

        using (var stream = ((PushStreamContent)context.Object))
        {
            var response = context.HttpContext.Response;
            if (context.ContentType != null)
            {
                response.ContentType = context.ContentType.ToString();
            }

            await stream.CopyToAsync(response.Body);
        }
    }
}

Instead of wrapping the HttpResponseMessage in the ObjectResult in your controller, you'll want to just shove the PushStreamContent object into the ObjectResult instead.与其将HttpResponseMessage包装在控制器中的ObjectResult中, PushStreamContentPushStreamContent对象推入ObjectResult You still need to set the MediaTypeHeaderValue on the ObjectResult .您仍然需要在ObjectResult上设置MediaTypeHeaderValue

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM