安全摄像头返回的HttpWebResponse响应内容类型为multipart/x-mixed-replace; boundary=--myboundary,其中包含MJPEG格式的数据,但无法正常工作。

12
我有一个ASP.NET应用程序,需要显示来自安全摄像头的视频源。该视频流具有“multipart / x-mixed-replace; boundary = --myboundary”的内容类型,并且映像数据位于边界之间。我需要帮助将该数据流传递到我的页面,以便客户端插件可以像直接浏览摄像头Web界面一样使用流。 以下代码无效:
//Get response data
byte[] data = HtmlParser.GetByteArrayFromStream(response.GetResponseStream());
if (data != null)
{
 HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
}
return;
3个回答

20

如果你希望客户端能够看到MJPEG流,你需要发送整个HTTP响应。像浏览器这样的HTTP客户端或者像VLC这样的媒体播放器需要一个类似于以下结构的MJPEG流:

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=myboundary

--myboundary
Content-Type: image/jpeg
Content-length: 12345

[image 1 encoded jpeg data]


--myboundary
Content-Type: image/jpeg
Content-length: 45678

[image 2 encoded jpeg data]

...

注意:正如Ergousha在一个答案中所说的,Content-length字段后必须有一个空行。

顺便问一下,为什么不直接将客户端重定向到mjpeg流?

例如,您可以使用http://ipcam/mjpg/video.mjpg AXIS IP摄像头。

如果您只需要通过HTTP获取图像,则必须设置正确的标头和MIME内容类型image/jpeg。要解码图像,您必须获取字节数据,然后您将获得JPEG编码。然后,您将需要解码JPEG以获取特定格式的图像(我认为类似于yuv420p)。我已经检查过我的IP摄像机,它的流似乎没有进行base64编码。

明确您的需求,我会尽力提供更多帮助。

我的意见。

编辑:

好吧,我想你要做的事情是:

client    : connect to proxy, 
            get example.com/camera1.mjpg,
            while not the end
                recv


yourproxy : wait connection
            connect to camera,
            get 10.0.0.123/camera1.mjpg
            while not the end
                recv buffer
                copy buffer
                send buffer to client

这意味着您必须向客户端发送正确的标头。为确保正确性,请使用诸如wireshark之类的工具来监视数据包,并确保在客户端发出HTTP GET请求后,向其发送正确的MJPEG流(就像我在帖子开头描述的那样...)

m2c


这正是我想做的。由于我的应用程序充当反向代理,因此我无法直接将用户重定向到mjpeg流。因此,我需要从摄像机接收流,然后将其作为响应发送到我的应用程序中的URL。因此,HTTP客户端调用http://example.com/camera1.mjpg 我的服务器解析请求并调用位于http://10.1.1.240/mjpg/video.mjpg的camera1 然后,我需要将响应流回传给客户端。这就是我一直在努力解决如何将mjpg流无修改地返回给客户端的困难所在。 - arri.io
请更准确地描述您的困难。从您的代码片段来看,似乎您只读取了响应的一部分。使用HTTP/MJPEG,您必须不断读取TCP数据包并重新发送它们,因此我的答案中有伪代码。我猜GetByteArrayFromStream调用部分读取了数据,因此您只向客户端发送了部分数据。您必须在TCP通道上持续读取直到其关闭!使用wireshark检查您接收/发送的内容,这将是真相。如果我误解了您的问题,请明确说明... - neuro
是的,我非常确定我们需要深入一些,使用一些不那么抽象的东西,比如 TcpClient。我目前正在尝试做与 @arri.me 相同的事情! - Josh Stodola
2
应该是 boundary=myboundary 而不是 boundary=--myboundary!破折号应该只包含在消息正文中,而不是多部分消息的头部,请参见 RFC 1341。在解码这样的流时,应该为两种情况做好准备(正如我刚刚吃过苦头学到的)。 - devconsole

7

关于mjpeg流的外观,这是一个很好的解释。我想补充一点提示; 实际数据之前始终有两个换行符。如果您将其变为一行,则无法正常工作。

        string header =
            "--myboundary\r\n" +
            "Content-Type:image/jpeg\r\n" +
            "Content-Length:" + length.ToString() + "\r\n\r\n";

你是怎么知道这个的?我花了好几个小时才找到这段代码,而它恰好包含了你所写的内容。你是怎么知道这个的?你能介绍一些教授这些东西的资源吗? - sadati
我只是在进行实验。试错;观察和分析工作流程。 - Angry Bird

1

图片数据的编码是什么?是Base64吗?

基本上,您需要从响应中解析出图像数据,将其Base64解码为字节,然后将图像发送给客户端。


不需要解码/编码,因为流必须作为MJPEG转发到客户端。 :) - neuro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接