0

我正在构建一个基于ASP.NET Core的小型Web应用程序。我的应用程序是通过服务将视频从客户端传输到客户端。保持连接活着在ASP.NET Core中流式传输

我已经按照这个帖子:

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

我已经成功地实现教程的应用程序,但是,这是从服务器的视频流给客户。

我想现在要做的是:

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

以下是我已经实现:

(Index.cshtml)

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

StreamingService

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的数据时。对于循环运行,我得到一个异常说,流已被处置。

我的问题是:

  • 我怎能流活着流?

(在API /视频创建流/发起保持活着,当客户端调用API /视频/广播,都开始流将更新它的日期,而不必设置)

谢谢

回答

0

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

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

只需将流添加到缓存,并在下一次点击api/video/broadcast时使用缓存流。

请注意,如果您在网络农场或托管在云中,建议您使用Distributed Cache(如Redis缓存),否则您的缓存可能会消失。例如,使用Azure Redis Cache这很好用!

+0

但是当我访问它时丢弃了流。我可以通过使用IMemoryCache保持客户端和服务器之间的连接吗? – Redplane

+0

我的不好,我应该先问你一件事。如何注册IStreamingService?哪一辈子?瞬态,范围或Singleton? –

+0

我使用IStreamingService作为单例(services.AddSingeton ()) – Redplane