【问题标题】:it is possible to stream video with SignalR?可以使用 SignalR 流式传输视频吗?
【发布时间】:2022-05-21 02:54:58
【问题描述】:

好吧,我正在尝试对视频流进行证明,我正在使用 asp.net c#。 我有点迷茫,你有什么想法或建议吗?

【问题讨论】:

  • 它不会是完成这项工作的最佳工具。有些人用螺丝刀代替锤子,用砖头代替锤子,也用同样的砖头将螺丝钉入木头,他们最终得到了杰作。如果您负担得起,正确的工具将使工作分配变得更容易,并且在此过程中减少您的头痛。 SignalR 中使用的技术对于流式视频没有多大用处。而是尝试将 IceCast 移植到 .net。

标签: signalr signalr-hub signalr.client


【解决方案1】:

我在 SignalR 之上实现了视频流。你可以在http://weblogs.asp.net/ricardoperes/archive/2014/04/24/video-streaming-with-asp-net-signalr-and-html5.aspx找到我的例子。

【讨论】:

  • 链接已损坏 :)
  • 它没有坏,显然是weblogs.asp.net的问题...应该尽快修复,希望!
  • 还是不行,没有备用链接,repo 什么的?
  • 网站回来了
【解决方案2】:

不,SignalR 基于仅流式传输基于文本的 JSON 消息的标准(WebSockets、LongPolling、ForeverFrame 等)。您最好查看WebRTC specification。现在,您可以通过使用 SignalR 发送控制消息来将这两种技术结合在一起,该消息会触发一些 JavaScript,从而更改浏览器当前显示的 WebRTC 提要。

【讨论】:

  • 现在支持MessagePack。您甚至可以注入您的自定义中心消息序列化程序。
【解决方案3】:

是的,最新版本的 SignalR 内核支持streaming
微软提供的一些samples

【讨论】:

    【解决方案4】:

    我不知道 SignalR 是否用于处理视频流,但 SignalR 是客户端到客户端客户端到服务器和服务器到客户端之间的集线器容器。如果我想要视频聊天,为什么我不能将它用作我的中心?无论如何,SignalR 也可以处理字节数组,而不仅仅是字符串,然后让我们尝试将每个帧作为字节 [](流)发送。至少当我只使用 .Net 时,我可以集线器字节 []。当我输入 Python 时,我需要使用 base64 序列化为字符串,它也可以从我的 PI 中工作。 关注我推入 GIT 的实验室解决方案。 https://github.com/Guille1878/VideoChat

    SignalR Hub(默认,非无服务器)

    namespace ChatHub
    {
        public interface IVideoChatClient
        {
            Task DownloadStream(byte[] stream);
        }
    
        public class VideoChatHub : Hub<IVideoChatClient> 
        {
            public async Task UploadStream(byte[] stream)
            {
                await Clients.All.DownloadStream(stream);
            }
        }
    }
    

    视频发送器:(UWP)

    while (isStreamingOut)
    {
          var previewProperties = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
    
          VideoFrame videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);
        
          Var frame = await mediaCapture.GetPreviewFrameAsync(videoFrame)
    
          if (frame == null)
          {
                await Task.Delay(delayMilliSeconds);
                continue;
          }
    
          var memoryRandomAccessStream = new InMemoryRandomAccessStream();
          var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, memoryRandomAccessStream);
          encoder.SetSoftwareBitmap(frame.SoftwareBitmap);  
          encoder.IsThumbnailGenerated = false;
          await encoder.FlushAsync();
    
          try
          {
                 var array = new byte[memoryRandomAccessStream.Size];
                 await memoryRandomAccessStream.ReadAsync(array.AsBuffer(), (uint)memoryRandomAccessStream.Size, InputStreamOptions.None);
    
                 if (array.Any())
                      await connection.InvokeAsync("UploadStream", array);                   
           }
           catch (Exception ex)
           {
                  System.Diagnostics.Debug.WriteLine(ex.Message);
           }
    
           await Task.Delay(5);
    }
    

    视频接收器:(UWP)

    private async void StreamVideo_Click(object sender, RoutedEventArgs e)
    {
          isStreamingIn = StreamVideo.IsChecked ?? false;
          if (isStreamingIn)
          {
                hubConnection.On<byte[]>("DownloadStream", (stream) =>
                {
                      _ = this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                      {
                           if (isStreamingIn)
                               StreamedArraysQueue.Enqueue(stream);
                      });
                 });
    
                 if (hubConnection.State == HubConnectionState.Disconnected)
                      await hubConnection.StartAsync();
    
                  _ = BuildImageFrames();
               }
           }     
    }
    
    private async Task BuildImageFrames()
    {
          while (isStreamingIn)
          {
                await Task.Delay(5);
    
                StreamedArraysQueue.TryDequeue(out byte[] buffer);
    
                if (!(buffer?.Any() ?? false))
                      continue;
    
                try
                {
                        var randomAccessStream = new InMemoryRandomAccessStream();
                        await randomAccessStream.WriteAsync(buffer.AsBuffer());
                        randomAccessStream.Seek(0); 
                        await randomAccessStream.FlushAsync();
    
                        var decoder = await BitmapDecoder.CreateAsync(randomAccessStream);
    
                        var softwareBitmap = await decoder.GetSoftwareBitmapAsync();
    
                        var imageSource = await ConvertToSoftwareBitmapSource(softwareBitmap);
    
                        ImageVideo.Source = imageSource;
                 }
                 catch (Exception ex)
                 {
                        System.Diagnostics.Debug.WriteLine(ex.Message);
                 }
           }
    }
    

    我正在使用“SignalR Core”

    【讨论】:

    • 现在不行。我的代码发送图像(帧)和文本消息。但我也需要语音,稍后我将使用语音实时发送。如果您只想发送像 Whatsapp 这样的短音频,那么很容易,您可以将音频作为字节 [] 中的流发送。但直播音频面临更多挑战。稍后我将在下一个实验室中使用它。
    • 如果你成功了,请告诉我。我真的需要那段代码!提前致谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    相关资源
    最近更新 更多