C# WebAPI PushStreamContent客户端读取视频流

C# WebAPI PushStreamContent客户端读取视频流,c#,asp.net-web-api,video-streaming,C#,Asp.net Web Api,Video Streaming,我有一个通过webapi曝光的相机。此相机返回jpeg帧。在服务器端,我使用以下方法: [Route("api/v1/camera/live/stream")] [HttpGet] public HttpResponseMessage GetStream() { logger.Trace($"GET api/v1/camera/live/stream called"); var response = Request.CreateResponse(HttpStatusCode.P

我有一个通过webapi曝光的相机。此相机返回jpeg帧。在服务器端,我使用以下方法:

[Route("api/v1/camera/live/stream")]
[HttpGet]
public HttpResponseMessage GetStream()
{
    logger.Trace($"GET api/v1/camera/live/stream called");

    var response = Request.CreateResponse(HttpStatusCode.PartialContent);
    response.Content = new PushStreamContent(new Action<Stream, HttpContent, TransportContext>(async (stream, content, tansportContext) =>
    {
        EventHandler<AcquiredDataEventArgs<CameraFrame>> handler = (_, __) => { };
        try
        {
            MjpegWriter writer = new MjpegWriter(stream);
            handler = (s, e) => writer.Write(e.Data.Image.GetJpegStream());

            camera.DataAcquired += handler;
            while (HttpContext.Current.Response.IsClientConnected)
            {
                await Task.Delay(100);
            }
            camera.DataAcquired -= handler;
        }
        catch (Exception ex)
        {
            logger.Error($"Streaming error", ex);
            throw;
        }
        logger.Trace("streaming ended");

    }));

    response.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/x-mixed-replace; boundary=--boundary");

    return response;
}
[路由(“api/v1/camera/live/stream”)]
[HttpGet]
公共HttpResponseMessage GetStream()
{
Trace($“调用getapi/v1/camera/live/stream”);
var response=Request.CreateResponse(HttpStatusCode.PartialContent);
response.Content=新的PushStreamContent(新操作(异步(流、内容、tansportContext)=>
{
EventHandler处理程序=(,_)=>{};
尝试
{
MjpegWriter=新的MjpegWriter(流);
handler=(s,e)=>writer.Write(e.Data.Image.GetJpegStream());
camera.DataAcquired+=处理程序;
while(HttpContext.Current.Response.IsClientConnected)
{
等待任务。延迟(100);
}
camera.DataAcquired-=处理程序;
}
捕获(例外情况除外)
{
logger.Error($“流错误”,ex);
投掷;
}
logger.Trace(“流结束”);
}));
response.Content.Headers.ContentType=MediaTypeHeaderValue.Parse(“multipart/x-mixed-replace;boundary=--boundary”);
返回响应;
}
我想在WPF应用程序中实时显示此视频流。
如果我通过网络浏览器打开视频流,它会很好地流式播放视频。。。但如何将流传输到c#客户端应用程序

您可以为此使用HttpClient。只需通过设置
HttpCompletionOption.ResponseHeadersRead
确保不缓冲响应即可

using (var httpClient = new HttpClient())
using (var response = await httpClient.GetAsync("http://...",
    HttpCompletionOption.ResponseHeadersRead))
using (Stream stream = await response.Content.ReadAsStreamAsync())
{
    // Do whatever with the resulting stream.
}

您可以使用HttpClient进行此操作。只需通过设置
HttpCompletionOption.ResponseHeadersRead
确保不缓冲响应即可

using (var httpClient = new HttpClient())
using (var response = await httpClient.GetAsync("http://...",
    HttpCompletionOption.ResponseHeadersRead))
using (Stream stream = await response.Content.ReadAsStreamAsync())
{
    // Do whatever with the resulting stream.
}
Lib(可通过nuget获得)Emgu.CV是OpenCV上的一个C#包装器,可以接收流

using Emgu.CV;

...

    private void StartWatching()
    {
        Task.Run(() =>
        {
            try
            {
                capture = new VideoCapture(headConfiguration.CameraStreamingUri.ToString());
                capture.ImageGrabbed += Capture_ImageGrabbed;
                capture.Start(ExceptionHandler.AlwaysHandle);
            }
            catch (Exception ex)
            {
                capture = null;
                Logger.Error(ex);
                throw ex;
            }
        });
    }

    private void Capture_ImageGrabbed(object sender, EventArgs e)
    {
        if (capture == null || OnNewCameraFrame == null)
        {
            return;
        }

        try
        {
            var frame = new Mat();
            if (capture.Retrieve(frame))
            {
                var output = new ByteImage(frame.Width, frame.Height, frame.Step);

                Marshal.Copy(frame.DataPointer, output.Data, 0, output.Height * output.Stride);

                OnNewCameraFrame?.Invoke(this, new ValueChangeArgs<ByteImage>(output));
            }
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
        }
    }
使用Emgu.CV;
...
私有void StartWatching()
{
Task.Run(()=>
{
尝试
{
capture=新视频捕获(headConfiguration.CameraStreamingUri.ToString());
capture.image抓取+=捕获\u image抓取;
capture.Start(ExceptionHandler.AlwaysHandle);
}
捕获(例外情况除外)
{
捕获=空;
记录器错误(ex);
掷骰子;
}
});
}
私有无效捕获(对象发送方,事件参数e)
{
if(捕获==null | | OnNewCameraFrame==null)
{
返回;
}
尝试
{
var frame=新的Mat();
if(捕获、检索(帧))
{
var输出=新的ByteImage(frame.Width、frame.Height、frame.Step);
Marshal.Copy(frame.DataPointer,output.Data,0,output.Height*output.Stride);
OnNewCameraFrame?.Invoke(这个,新的值changeargs(输出));
}
}
捕获(例外情况除外)
{
记录器错误(ex);
}
}
Lib(可通过nuget获得)Emgu.CV是OpenCV上的C#包装器,可以接收流

using Emgu.CV;

...

    private void StartWatching()
    {
        Task.Run(() =>
        {
            try
            {
                capture = new VideoCapture(headConfiguration.CameraStreamingUri.ToString());
                capture.ImageGrabbed += Capture_ImageGrabbed;
                capture.Start(ExceptionHandler.AlwaysHandle);
            }
            catch (Exception ex)
            {
                capture = null;
                Logger.Error(ex);
                throw ex;
            }
        });
    }

    private void Capture_ImageGrabbed(object sender, EventArgs e)
    {
        if (capture == null || OnNewCameraFrame == null)
        {
            return;
        }

        try
        {
            var frame = new Mat();
            if (capture.Retrieve(frame))
            {
                var output = new ByteImage(frame.Width, frame.Height, frame.Step);

                Marshal.Copy(frame.DataPointer, output.Data, 0, output.Height * output.Stride);

                OnNewCameraFrame?.Invoke(this, new ValueChangeArgs<ByteImage>(output));
            }
        }
        catch (Exception ex)
        {
            Logger.Error(ex);
        }
    }
使用Emgu.CV;
...
私有void StartWatching()
{
Task.Run(()=>
{
尝试
{
capture=新视频捕获(headConfiguration.CameraStreamingUri.ToString());
capture.image抓取+=捕获\u image抓取;
capture.Start(ExceptionHandler.AlwaysHandle);
}
捕获(例外情况除外)
{
捕获=空;
记录器错误(ex);
掷骰子;
}
});
}
私有无效捕获(对象发送方,事件参数e)
{
if(捕获==null | | OnNewCameraFrame==null)
{
返回;
}
尝试
{
var frame=新的Mat();
if(捕获、检索(帧))
{
var输出=新的ByteImage(frame.Width、frame.Height、frame.Step);
Marshal.Copy(frame.DataPointer,output.Data,0,output.Height*output.Stride);
OnNewCameraFrame?.Invoke(这个,新的值changeargs(输出));
}
}
捕获(例外情况除外)
{
记录器错误(ex);
}
}