我有一个连接到ESP8266(12-E)模块的arducam微型2MP相机,我试图在一个窗口内实现视频流,窗口周围带有一些文本和控制按钮,所有这些都在同一浏览器选项卡/页面中。我创建了两个HTML页面供服务器使用。第一个是主页,没有图像流,只有一个带有文本按钮和一些CSS的简单页面。第二个HTML页面将连续的帧(流视频)与一些文本和按钮一起提供给浏览器。将主页发送到浏览器后,所有内容均按我期望的方式显示。但是,当提供第二个HTML网页时,当浏览器(Firefox或Chrome)从服务器(esp12-e)收到答复时,会发生一些奇怪的事情。

通常,我希望有一个小窗口,显示从摄像机拍摄的连续帧,在该窗口上有一些文本,并在其下面有一些控制按钮。
但是,不会发生两件事。
/>

只有视频流窗口显示在浏览器的选项卡中,但是在该窗口周围只有灰色背景色。没有按钮,没有文本。当我在“ head”内打开HTML Inspector时,有几行HTML代码创建了背景灰色,还有一些我没有在服务器中编写的CSS东西。浏览器以某种方式自动创建此代码行,并将其添加到我的原始HTML代码中。
在我的原始HTML代码中的“正文”中,以及流窗口的代码中,我具有将要显示的文本和按钮元素的代码。但是在浏览器中,这些部分消失了。当我打开检查器时,这些元素不存在!到目前为止,我已经尝试了各种方法来避免这种情况,方法是隔离/嵌入浏览器选项卡中的流窗口。这些方法是:iframe,数据URI,多部分/ x混合替换,表单。不幸的是,所有这些方法(灰色背景色,屏幕中间的流窗口以及消失的按钮和文本)都发生了相同的结果。

我唯一知道的是,当浏览器从服务器“看到”传入的图像时,会产生这些副作用。当我仅使用文本和按钮创建HTML时,它显示得很好。我在这里做错了什么,但我找不到它。

在下面,我附上两张我在浏览器选项卡中得到的图片以及从esp-12e服务器发送来进行照片捕获的HTML代码。

void serveWebpage(WiFiClient client){

  String answer = "HTTP/1.1 200 OK\r\n";     
  answer += "Content-Type: text/html\r\n\r\n";
  answer +="<!DOCTYPE HTML>\r\n"; 

  answer += "<html>\r\n";
  answer +="<head><title> Monitor </title></head>\r\n";

  answer += "<body>\r\n";
  answer += "<h1 style=\"position:relative; left:25px;\"> &#9875     Observation Panel &#9875</h1>\r\n";     // Header Text

  answer += "<a href=\"/videoStream\"><button type=\"button\"  style=\"position:absolute; top:340px;";   // First Button
  answer += "left:95px; color:blue; height:70px; width:90px; font-weight: bold; border-style:outset;";
  answer += "border-width:2px; border-color:black;\"> Video Stream </button></a>\r\n";

  answer += "<a href=\"PhotoCapture\"><button type=\"button\"  style=\"position:absolute; top:340px;";   // Second Button
  answer += "left:195px; color:blue; height:70px; width:90px; font-weight: bold; border-style:outset;";
  answer += "border-width:2px; border-color:black;\"> Video Stream </button></a>\r\n";

  answer += "<div>\r\n";
  answer += "<img src='data:image/jpeg; charset=utf-8; base64,";   // Here the image is wrapped with data URI to display it in the browser


       myCAM.clear_fifo_flag();    // this part is taken from the arducam library exammples. It captures the image and sends it to browser
       myCAM.start_capture();       

       while (!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));  // wait here until capture has completed
       size_t len = myCAM.read_fifo_length();

       myCAM.CS_LOW();         
       myCAM.set_fifo_burst();     

       #if !(defined (ARDUCAM_SHIELD_V2) && defined (OV2640_CAM))
       SPI.transfer(0xFF);
       #endif   

       static const size_t bufferSize = 4096; //4096
       static uint8_t buffer[bufferSize] = {0xFF};

       while (len) {                
         size_t will_copy = (len < bufferSize) ? len : bufferSize;
         SPI.transferBytes(&buffer[0], &buffer[0], will_copy);
         if (!client.connected()) break;

         client.write(&buffer[0], will_copy);
         len -= will_copy;
       }
  myCAM.CS_HIGH();

  answer +="9k=' />"; // closing the <img> 
  answer +="</div>\r\n";
  answer +="</body>\r\n";
  answer +="</html>\r\n\r\n";

  client.print(answer);  
}  





我终于取得了一些进步,但不是100%。我通过在iframe元素内使用数据URI方法将图像中的jpeg格式的数据嵌入到iframe中,从而设法在iframe中显示jpeg图像。

    string = "<iframe srcdoc='<img src=\"data:html/text;base64,/9j/4AAQ..... \" > ' > "; 


我的错误是我没有使用正确顺序的引号,并且图像数据在浏览器中被解释为文本。然后,我尝试使用用于将捕获的图像从相机发送到浏览器的功能执行相同的操作。不幸的是,出现了同样的问题,这次我无法修复。当我向浏览器发送带有多个引号的字符串时,会发生某些情况,因为它会将字符串解释为文本而不是jpeg数据格式,例如:/ 9j / 4AAQ ...我从浏览器的检查器上传了一张图片(显示了浏览器的当我使用相机发送的帧数据的功能时接收到的数据)更容易理解我的意思。有什么想法吗?



这里是对我到目前为止完成的工作的回顾。我创建了一个HTML,其中包含Iframe和一些按钮。 iframe和按钮均正确显示在同一浏览器的标签中。现在,在iframe内,我放置了srcdoc属性,并将原始jpeg数据直接插入(样本jpeg图像的)中,因为它们是经过编码的(base64),但是浏览器将这些jpeg数据解释为纯文本并将其在iframe中显示为文本。然后,我使用了srcdoc中的图片标签将原始jpeg数据包装到iframe中。在对iframe字符串中的引号进行了一些错误之后,此方法有效。
然后我从图像标签中删除了原始jpeg数据,并将其替换为从相机中获取jpeg数据的功能。我发送答案字符串的第一部分(打开iframe和img标签),然后从相机发送数据,最后我发送答案字符串的第二部分(关闭iframe和img标签)。通常,它应该可以正常工作,因为我遵循与以前相同的步骤。但是浏览器无法再次解释图像。

在下面,我添加了编码示例图像(浏览器解释为图像)的代码部分,然后添加了照相机功能(将其解释为奇数而不是图像的代码部分)进行比较。两者应该以相同的方式工作,但只有第一个可以工作。

编码的示例图像:

    answer = "<iframe srcdoc='<img src=\"data:image/jpeg;base64,/9j/4AAQS...0KDQo=\"> ' scrolling=\"no\" width=\"340\" height=\"340\" >  <p> Error </p> </iframe>\r\n ";


相机功能sendFrame():

    answer = "<iframe srcdoc=\"<img src='data:image/jpeg;base64,";
    client.print(answer);
    sendFrame();
    answer ="' > \" >  <p> Error </p> </iframe>\r\n ";
    client.print(answer);


所以,我想我已经发现相机传入的jpeg数据出了什么问题相机功能将jpeg数据(以格式传递给服务器,然后传递给客户端)浏览器会将其解释为文本或类似内容,因为其中包含奇怪的字符(请检查我发布的最后一张图片)。

此外,为了编写html代码,我使用引号“和”(或“和\”)创建iframe代码以及iframe中的所有其他内容。

这里就是这样:因为浏览器将某些相机的jpeg数据解释为引号,所以它们与我放入iframe中的引号进行交互以包装img标签和来自相机的数据,这就是为什么它将iframe中的所有内容弄乱了(我认为)

是否可以将来自照相机功能的图像数据转换为base64,以免它们与iframe和图像标签的包装引号相互作用?

评论

您是否可以在此处包含此问题的最小代码示例?我怀疑没有这些,任何答案都将只是猜测。我的猜测是,也许您只是在提供图片,或者使用错误的Content-Type提供图片,因为它显然被解释为图片(所有插入的样式均为Firefox内部样式)

第二张图片包含代码,但我将再上传一张。感谢您的帮助

如果有的话,我也在考虑服务器代码。您是在使用这样的预制库还是自己滚动库?

是的,我阅读了该代码,但是我想自己构建(以便更好地理解)。我会稍后上传

抱歉,我的回答延迟了,但是我整理了一下代码,以便于...可读。如前所述,我尝试了不同的方法。但是每次都发生相同的结果。所以一定是别的东西。我在这里迷路了

#1 楼

您是直接从网络摄像头将数据写入流,然后是要构建的空答案模板。

您可以看到,您没有将答案的第一部分写入wifi,而是将相机中的数据直接写入wifi。

因为您的相机数据已经格式化,所以建议您将数据添加到iframe而不是img标签(现在是,现在不属于img标签)。

void serveWebpage(WiFiClient client){

  String answer = "HTTP/1.1 200 OK\r\n";     
  answer += "Content-Type: text/html\r\n\r\n";
  answer +="<!DOCTYPE HTML>\r\n"; 

  answer += "<html>\r\n";
  answer +="<head><title> Monitor </title></head>\r\n";

  answer += "<body>\r\n";
  answer += "<h1 style=\"position:relative; left:25px;\"> &#9875     Observation Panel &#9875</h1>\r\n";     // Header Text

  answer += "<a href=\"/videoStream\"><button type=\"button\"  style=\"position:absolute; top:340px;";   // First Button
  answer += "left:95px; color:blue; height:70px; width:90px; font-weight: bold; border-style:outset;";
  answer += "border-width:2px; border-color:black;\"> Video Stream </button></a>\r\n";

  answer += "<a href=\"PhotoCapture\"><button type=\"button\"  style=\"position:absolute; top:340px;";   // Second Button
  answer += "left:195px; color:blue; height:70px; width:90px; font-weight: bold; border-style:outset;";
  answer += "border-width:2px; border-color:black;\"> Video Stream </button></a>\r\n";

  answer += "<div>\r\n";
  answer += "<iframe src="/yourURIforImage"></iframe>\r\n"; 
  answer +="</div>\r\n";
  answer +="</body>\r\n";
  answer +="</html>\r\n\r\n";

  client.print(answer);  
}  

void serveImage(WifiClient client) {
       myCAM.clear_fifo_flag();    // this part is taken from the arducam library exammples. It captures the image and sends it to browser
       myCAM.start_capture();       

       while (!myCAM.get_bit(ARDUCHIP_TRIG, CAP_DONE_MASK));  // wait here until capture has completed
       size_t len = myCAM.read_fifo_length();

       myCAM.CS_LOW();         
       myCAM.set_fifo_burst();     

       #if !(defined (ARDUCAM_SHIELD_V2) && defined (OV2640_CAM))
       SPI.transfer(0xFF);
       #endif   

       static const size_t bufferSize = 4096; //4096
       static uint8_t buffer[bufferSize] = {0xFF};

       while (len) {                
         size_t will_copy = (len < bufferSize) ? len : bufferSize;
         SPI.transferBytes(&buffer[0], &buffer[0], will_copy);
         if (!client.connected()) break;

         client.write(&buffer[0], will_copy);
         len -= will_copy;
       }
       myCAM.CS_HIGH();
}


,并在其中验证您对通过serveWebpage()做出响应的uri的相似之处,以匹配serveImage()和/ yourURIforImage。

评论


我遵循了您的意见,并在答案的第一部分之后立即添加了一个client.print(answer),现在可以看到一些进展。我保留了img元素以查看将要发生的情况。文本和按钮显示正确(我认为这是一个好兆头),但浏览器不会将图像数据解释为图像,而是奇数字符。自从将数据转换为base64后,为什么浏览器无法将图像数据理解为图像?我将添加一个iframe并删除img元素以查看会发生什么,然后我会回来

–闪闪发光
17年7月21日在23:17

我创建了一个iframe窗口,并尝试在其中嵌入使用数据URI方法从相机拍摄的图像。但是浏览器不会将图像数据解释为图像,并且iframe中会显示奇怪的字符。我也使用srcdoc而不是src来嵌入图像数据。有任何想法吗?

–闪闪发光
17年7月23日在18:44



为此,请首先编写一个仅成功返回图像的方法,然后在另一个方法中调用该方法