视频网站与Asp.Net的WebForms +的WebAPI + HTML5

问题描述:

的直播问题是这样的:视频网站与Asp.Net的WebForms +的WebAPI + HTML5

  1. 在服务器上有一个视频文件;
  2. 管理员在播放中运行它(视频广播开始);
  3. 用户连接到服务器 - 必须给予当前正在播放的视频流。实时网络直播。

为了实现这个任务,我把作为文章的基础: http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/
它的工作。为视频文件独立并行提供视频文件。 我正在看。

接下来有必要解决广播给多个客户的问题(工作中的第3段)。我把这篇文章: http://gigi.nullneuron.net/gigilabs/streaming-data-with-asp-net-web-api-and-pushcontentstream/

由于我必须在视频字节中提供证据 - 我将StreamWriter类替换为Stream。
它适用于第一个客户端。

我做了一个网站Asp.Net WebForms + WebApi + HTML5。 网页 - 运行视频管理器并由用户查看。 WebApi为玩家提供<video>(HTML5)视频流。

HTML5:

<video> 
    <source src="http://localhost:8080/SiteVideoStreaming/api/live/?filename=nameFile" /> 
</video> 

的WebAPI控制器:

//Controllers 
public class LiveController : ApiController 
{ 
    private static ConcurrentBag<Stream> clients; // List of clients who need to simultaneously deliver video data 
    static string fileName = ""; 

    static LiveController() 
    { 
     clients = new ConcurrentBag<Stream>(); 
     WriteToStream(); // The first call - start to play a video file 
    } 

    [HttpGet] 
    public HttpResponseMessage Subscribe(string filename) 
    { 
     fileName = HostingEnvironment.MapPath("~/Videos/") + filename; 

     var response = Request.CreateResponse(); 
     response.Content = new PushStreamContent((a, b, c) => { OnStreamAvailable(a, b, c); }, "video/mp4"); 
     return response; 
    } 


    private void OnStreamAvailable(Stream stream, HttpContent content, TransportContext context) 
    { 
     clients.Add(stream); // Add new client 
    } 

    //Class record a video file into a streams 
    public async static void WriteToStream() 
    { 
     var buffer = new byte[65536]; 

     using (var video = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      var length = (int)video.Length; 
      var bytesRead = 1; 

      while (length > 0 && bytesRead > 0) 
      { 
       bytesRead = video.Read(buffer, 0, Math.Min(length, buffer.Length)); 

       foreach (var client in clients)// Each client in turn we return video data 
       { 
        try 
        { 
         await client.WriteAsync(buffer, 0, bytesRead); // ERROR - here !!! when you connect a second client 
         await client.FlushAsync(); 
        } 
        catch (Exception ex) 
        { 
         Stream ignore; 
         clients.TryTake(out ignore); 
        } 
       } 

       length -= bytesRead; 
      } 
     } 
    } 
} 

如果请求首先从一个客户来了 - 赋予视频。加工。 如果来自第二个客户端的请求 - 当您尝试开始给他一个流错误发生。 在这方面滴和第一个客户端。

该错误是如下:{ “远程主机关闭了连接 错误代码是0x800704CD”}

[System.Web.HttpException] =

正如我在因特网上搜索后可以理解为:

0x800704CD“试图在不存在的网络 连接上进行操作。”

告诉我我做得不对吗? 谢谢。

我这样做。 我用这个控制器:

public class VideoController : ApiController 
{ 

    // GET api/<controller> 
    public HttpResponseMessage Get(string filename) 
    { 
     if (filename == null) 
      return new HttpResponseMessage(HttpStatusCode.BadRequest); 

     string filePath = HostingEnvironment.MapPath("~/Videos/") + filename; 

     if (Request.Headers.Range != null) 
     { 
      //Range Specifc request: Stream video on wanted range. 
      try 
      { 
       //NOTE: ETag calculation only with file name is one approach (Not the best one though - GUIDs or DateTime is may required in live applications.). 
       Encoder stringEncoder = Encoding.UTF8.GetEncoder(); 
       byte[] stringBytes = new byte[stringEncoder.GetByteCount(filePath.ToCharArray(), 0, filePath.Length, true)]; 
       stringEncoder.GetBytes(filePath.ToCharArray(), 0, filePath.Length, stringBytes, 0, true); 
       MD5CryptoServiceProvider MD5Enc = new MD5CryptoServiceProvider(); 
       string hash = BitConverter.ToString(MD5Enc.ComputeHash(stringBytes)).Replace("-", string.Empty); 

       HttpResponseMessage partialResponse = Request.CreateResponse(HttpStatusCode.PartialContent); 
       partialResponse.Headers.AcceptRanges.Add("bytes"); 
       partialResponse.Headers.ETag = new EntityTagHeaderValue("\"" + hash + "\""); 

       var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); 
       partialResponse.Content = new ByteRangeStreamContent(stream, Request.Headers.Range, new MediaTypeHeaderValue("video/mp4")); 
       return partialResponse; 
      } 
      catch (Exception ex) 
      { 
       return new HttpResponseMessage(HttpStatusCode.InternalServerError); 
      } 
     } 
     else 
     { 
      return new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable); 
     } 
    } 
} 

在客户端 - 我运行它<video>视频播放器通过技术SignalR。