La ventana de transmisión de video ESP12-E, el texto y los botones no se muestran como se esperaba


8

Tengo una cámara arducam mini 2MP conectada a un módulo ESP8266 (12-E) y estoy tratando de implementar la transmisión de video dentro de una ventana con algunos botones de texto y control alrededor, todo en la misma pestaña / página del navegador. He creado dos páginas HTML para que el servidor las use. La primera es la página web de inicio sin transmisión de imágenes, solo una página simple con botones de texto y algo de CSS. La segunda página HTML sirve los cuadros continuos (transmisión de video) junto con algunos textos y botones para el navegador. Cuando la página de inicio se envía al navegador, todo se muestra de la manera que esperaba. Pero, cuando se sirve la segunda página web HTML, pero suceden algunas cosas extrañas cuando el navegador (Firefox o Chrome) recibe la respuesta del servidor (esp12-e).

Normalmente esperaría una pequeña ventana que muestre cuadros continuos tomados de la cámara con algo de texto sobre esa ventana y algunos botones de control debajo de ella. Pero, en lugar de eso, suceden dos cosas.

  1. Solo se muestra la ventana de transmisión de video en la pestaña del navegador, pero alrededor de esta ventana solo hay un color de fondo gris. Sin botones ni texto. Cuando abro el Inspector HTML, dentro del "encabezado", hay algunas líneas de código HTML que crean el color gris de fondo y algunas cosas CSS que no he escrito en mi servidor. De alguna manera, el navegador crea estas líneas de código automáticamente y las agrega en mi código HTML original.
  2. En mi código HTML original, dentro del "cuerpo", junto con el código de la ventana de transmisión, tengo el código para los elementos de texto y botón que se mostrarán. Pero en el navegador, estas partes desaparecen. Cuando abro el Inspector, estos elementos no existen. He intentado varios enfoques hasta ahora para evitar esta situación aislando / incrustando la ventana de transmisión dentro de la pestaña del navegador. Estos enfoques son: iframe, URI de datos, reemplazo multipart / x-mixed, forma. Desafortunadamente, se produjo el mismo resultado para todos estos enfoques (color de fondo gris, ventana de transmisión en el medio de la pantalla y botones y texto desaparecidos).

Lo único que sé es que, cuando el navegador "ve" la imagen entrante del servidor, produce estos efectos secundarios. Cuando creo un HTML solo con texto y botones, se muestra muy bien. Hago algo mal aquí, pero no puedo encontrar lo que es.

A continuación adjunto 2 imágenes de lo que obtengo en la pestaña del navegador y el código HTML que envío desde el servidor esp-12e para una captura de fotos

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);  
}  

Video Window_missing botones y texto Código HTML que he escrito para ser servido por el servidor esp-12e

Finalmente progresé, pero no al 100%. Logré mostrar imágenes jpeg en el iframe incrustando datos en formato jpeg de una imagen con método URI de datos dentro del elemento Iframe.

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

Mi error fue que no utilicé las comillas con el orden correcto y los datos de la imagen se interpretaron como texto en el navegador. Luego intenté hacer lo mismo con la función que uso para enviar la imagen capturada de la cámara al navegador. Desafortunadamente, surgió el mismo problema y no puedo solucionarlo esta vez. Algo que sucede cuando envío una cadena con varias comillas al navegador porque las interpreta como texto y no como un formato de datos jpeg como este: / 9j / 4AAQ ...... Subí una imagen del inspector de mi navegador (mostrando el recibí datos cuando uso la función para los datos de cuadro enviados de la cámara) para entender más fácilmente lo que quiero decir. ¿Alguna idea sobre esto?

Los datos se interpretan defectuosos debido a las comillas múltiples (?)

Aquí hay una revisión de lo que he completado hasta ahora.Creé un HTML con un Iframe dentro y también algunos botones. Tanto el iframe como los botones se muestran correctamente en la misma pestaña del navegador. Ahora, dentro del iframe puse el atributo srcdoc e inserté los datos jpeg sin procesar directamente allí (de una imagen jpeg de muestra) ya que están codificados (base64) pero el navegador interpretó estos datos jpeg como texto sin formato y los mostró en el iframe como texto. Luego usé la etiqueta de imagen dentro de srcdoc para envolver los datos sin formato JPEG en el iframe. Esto funcionó después de algunos errores que hice con las comillas dentro de la cadena iframe. Luego eliminé los datos jpeg sin procesar de la etiqueta de imagen y los reemplacé con la función que trae datos jpeg de la cámara. Envío la primera parte de la cadena de respuesta (abriendo etiquetas iframe e img), luego envío los datos desde la cámara y finalmente envío la segunda parte de la cadena de respuesta (cierre las etiquetas iframe e img). Normalmente debería funcionar ya que seguí el mismo procedimiento que antes. Pero el navegador no pudo interpretar la imagen ... otra vez.

A continuación, he agregado las partes del código para la imagen de muestra codificada (que el navegador interpretó como imagen) y luego la función de cámara (que las interpretó como caracteres impares y no como imagen), para comparar. Ambos deberían funcionar de la misma manera, pero solo los primeros funcionan.

Imagen de muestra codificada:

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

Función de cámara sendFrame ():

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

Entonces, creo que he encontrado lo que falla con los datos jpeg entrantes de la cámara. La función de la cámara trae los datos jpeg (al servidor y luego al cliente) en un formato que el navegador lo interpreta como texto o algo así porque contiene personajes extraños (verifique la última imagen que publiqué).

También para escribir el código html utilizo comillas "y '(o" y \') para crear el código del iframe y todo lo demás dentro del iframe.

Y aquí está la cosa: dado que algunos de los datos jpeg de la cámara son interpretados como citas por el navegador, interactúan con las citas que puse dentro del iframe para envolver la etiqueta img y los datos que provienen de la cámara y es por eso que arruina todo en iframe (creo)

¿Hay alguna forma de convertir los datos de imagen que provienen de la función de la cámara en base64, para que no interactúen con las comillas del iframe y las etiquetas de imagen?


2
¿Es posible incluir aquí un ejemplo de código mínimo del problema? Sospecho que sin eso, cualquier respuesta sería especulación. Mi conjetura es que tal vez sólo está al servicio de la imagen, o servir con el mal Content-Type, ya que claramente está siendo interpretado como una imagen (todos los estilos insertados son estilos internos para Firefox )
Aurora0001

La segunda imagen incluye el código, pero subiré uno más. Gracias por la ayuda
Sparky

1
Estaba pensando en el código del servidor también, si lo tienes. ¿Estás utilizando una biblioteca prefabricada como esta o creaste la tuya propia?
Aurora0001

1
Sí, leí ese código pero pensé construirlo por mi cuenta (para entenderlo mejor). Lo subiré en un momento
Sparky

1
Disculpe la respuesta tardía, pero estaba ordenando un poco el código para ser ... legible. Probé diferentes métodos como mencioné antes. Pero el mismo resultado ocurrió cada vez. Entonces debe ser otra cosa. Estoy un poco perdido aquí
Sparky

Respuestas:


4

Está escribiendo directamente desde su cámara web los datos en la transmisión y luego viene la plantilla de respuesta vacía que está construyendo.

Puede ver, no escribe la primera parte de la respuesta a wifi y escribe datos de la cámara directamente en el wifi.

Debido a que sus datos de la cámara ya tienen un formato, sugeriría agregar datos al iframe en lugar de la etiqueta img, donde está ahora y no pertenece.

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();
}

y donde verifica a qué uri respondió con serveWebpage () que hace similar para que coincida con serveImage () y / yourURIforImage.


Seguí tu opinión y agregué un client.print (respuesta) inmediatamente después de la primera parte de la respuesta y ahora puedo ver algunos progresos. Mantuve el elemento img para ver qué va a pasar. El texto y el botón se muestran correctamente (creo que es una buena señal), pero el navegador no interpreta los datos de la imagen como una imagen, sino como caracteres extraños. ¿Por qué el navegador no entiende los datos de la imagen como imagen desde que convertí los datos a base64? Agregaré un iframe y borraré el elemento img para ver qué sucederá y volveré
Sparky

Creé una ventana de iframe y allí intenté incrustar la imagen tomada de la cámara con el método URI de datos. Pero los datos de la imagen no son interpretados como imagen por el navegador y se muestran caracteres extraños dentro del iframe. También usé srcdoc y no src para incrustar los datos de la imagen. ¿Algunas ideas?
Sparky

Para que esto funcione, primero escriba un método que devuelva con éxito la imagen solamente y luego, en otro método, llame a ese método <iframe src = "ruta a la imagen> </ iframe>
mico

Sí, no es mala idea, pero es que utilicé una imagen de la cámara de la siguiente manera: guardé la imagen jpeg capturada en mi PC, luego la codifiqué en base64 y finalmente la puse en el URI de datos srcdoc del iframe se visualizará.
Sparky

También puse los datos de la imagen directamente dentro de srcdoc sin etiqueta de imagen, pero el navegador los interpreta como caracteres. Caracteres extraños no solo letras o números.
Sparky

3

Lo que destaca es su declaración:

Algo sucede cuando envío una cadena con varias comillas al navegador porque las interpreta como texto y no como formato de datos jpeg como este: / 9j / 4AAQ ......

Recordé que hay una forma específica de incrustar citas es html: se necesitan algún tipo de caracteres de escape. Busqué en google

incrustar citas en html

Esta pregunta fue respondida en StackOverflow aquí:

¿Cómo escapar correctamente de las comillas dentro de los atributos html?

Parece que tienes comillas entre comillas. Por lo tanto, no estoy seguro de si ya está utilizando los caracteres de escape o no, pero sugeriría usar la opción explícita

&quot; 

para sus citas incrustadas.


Intentaré esto y te diré lo que pasó. & quote es lo mismo que \ "o '? Si uso & quote y \" y' en la misma cadena, cómo los interpretará el navegador. Gracias
Sparky

No estoy seguro. Pero hubo muchos resultados devueltos de una búsqueda en Google. Así que apostaría que la respuesta a esa pregunta se encontrará rápidamente, si realiza la búsqueda.
grldsndrs
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.