【问题标题】:Keep connection alive for streaming in ASP.NET Core在 ASP.NET Core 中保持连接以进行流式传输
【发布时间】:2017-03-16 12:41:21
【问题描述】:

我正在制作一个基于 ASP.NET Core 的小型 Web 应用程序。我的应用程序是通过服务将视频从客户端流式传输到客户端。

我已经关注了这篇文章:

http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

我已经成功实现了教程的应用,但是,那是用于从服务器到客户端的流式视频。

我现在想做的是:

  • 客户端注册到流媒体服务。 (使用视频或音频标签)
  • 服务接收客户端提交的数据(通过POSTMAN提交)
  • 服务将数据广播给每个注册的客户。

这是我实现的:

(Index.cshtml)

<div>
    <video  width="480" 
            height="320" 
            controls="controls" 
            autoplay="autoplay">
        <source     src="/api/video/initiate"
                    type="video/mp4">
        </source>
    </video>
</div>

流媒体服务

public class StreamingService: IStreamingService
{
    public IList<Stream> Connections {get;set;}

    public StreamingService()
    {
        Connections = new List<Stream>();
    }

    public byte[] AnalyzeStream(Stream stream)
    {
        long originalPosititon = 0;
        if (stream.CanSeek)
        {
            originalPosititon = stream.Position;
            stream.Position = 0;
        }

        try
        {
            var readBuffer = new byte[4096];
            int bytesReader;

            while ((byteRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
            {
                totalBytesRead += byteRead;

                if (totalBytesRead == readBuffer.Length)
                {
                    var nextByte = stream.ReadByte();
                    if (nextByte != -1)
                    {
                        var temp = new byte[readBuffer * 2];
                        Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                        Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                        readBuffer = temp;
                        totalBytesRead++;
                    }
                }
            }

            var buffer = readBuffer;
            if (readBuffer.Length != totalBytesRead)
            {
                buffer = new byte[totalBytesRead];
                Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
            }

            return buffer;
        }
        finally
        {
            if (stream.CanSeek)
                stream.Position = originalPosititon;
        }
    }
}

视频控制器

public class VideoController: Controller
{
    private readonly IStreamingService _streamingService;

    private readonly IHostingEnvironment _hostingEnvironment;

    public VideoController(IStreamingService streamingService, IHostingEnvironment hostingEnvironment)
    {
        _streamingService = streamingService;
        _hostingEnvironment = hostingEnvironment;
    }

    [HttpGet("initiate")]
    public IActionResult Initiate()
    {
        _streamingService.Connections.Add(Response.Body);
    }

    [HttpPost("broadcast")]
    public async Task<IActionResult> Broadcast()
    {
        // Retrieve data submitted from POSTMAN.
        var data = _streamingService.AnalyzeStream(Request.Body);

        foreach (var stream in _streamingService.Connections)
        {
            try
            {
                await stream.WriteAsync(data, 0, data.Length);
            }
            catch (Exception exception)
            {
                stream.Dispose();
                _streamingService.Connections.Remove(stream);
            }
        }
    }
}

当我通过 api/video/broadcast 从 POSTMAN 发送数据时。 For 循环运行,我得到一个异常说流已被释放。

我的问题是:

  • 我怎样才能让流保持活跃以进行流式传输?

(在 api/video/initiate 中创建的流保持活动状态,当客户端调用 api/video/broadcast 时,所有启动的流将更新其日期而无需释放)

谢谢,

【问题讨论】:

  • 嗨@Redplane,你找到解决方案了吗?我有同样的问题。

标签: asp.net-core video-streaming asp.net-core-mvc asp.net-core-webapi


【解决方案1】:

是否可以选择将流保存在缓存中?

您可以阅读更多关于它的信息here。最简单的方法是将缓存服务添加到依赖注入容器,并通过 VideoController 中的构造函数注入请求IMemoryCache 的具体实现(就像您对 IStreamingService 和 IHostingEnvironment 所做的那样)。

只需将流添加到缓存中,并在下次命中 api/video/broadcast 时使用缓存的流。

请注意,如果您在 webfarm 上或托管在云中,建议您使用 Distributed Cache,如 Redis 缓存,否则您的缓存可能会意外消失。例如,我使用Azure Redis Cache,效果很好!

【讨论】:

  • 但是当我访问它时,它被释放了。我可以使用 IMemoryCache 保持客户端和服务器之间的连接吗?
  • 我的错,我应该先问你一些事情。怎么得注册IStreamingService?哪一辈?瞬态、作用域还是单例?
  • 我使用 IStreamingService 作为 Singleton (services.AddSingeton())
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-15
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多