A janela de transmissão de vídeo ESP12-E, texto e botões não são exibidos conforme o esperado

8

Eu tenho uma câmera arducam mini 2MP conectada a um módulo ESP8266 (12-E) e estou tentando implementar o streaming de vídeo dentro de uma janela com alguns botões de texto e controle ao redor, tudo na mesma guia / página do navegador. Eu criei duas páginas HTML para o servidor usar. A primeira é a página inicial sem transmissão de imagens, apenas uma página simples com botões de texto e algum CSS. A segunda página HTML exibe os quadros contínuos (streaming de vídeo), juntamente com alguns textos e botões do navegador. Quando a página inicial é enviada para o navegador, tudo é exibido da maneira que eu espero. Porém, quando a segunda página da Web HTML é exibida, algumas coisas estranhas acontecem quando o navegador (Firefox ou Chrome) recebe a resposta do servidor (esp12-e).

Normalmente, eu esperaria uma pequena janela exibindo quadros contínuos tirados da câmera com algum texto sobre a janela e alguns botões de controle embaixo. Mas, em vez disso, duas coisas acontecem.

  1. Somente a janela de transmissão de vídeo é exibida na guia do navegador, mas nessa janela há apenas uma cor de fundo cinza. Sem botões, sem texto. Quando abro o HTML Inspector, dentro de "head", existem algumas linhas de código HTML que criam a cor cinza de fundo e algumas coisas CSS que não escrevi no meu servidor. De alguma forma, o navegador cria essas linhas de código automaticamente e as adiciona ao meu código HTML original.
  2. No meu código HTML original, dentro de "body", junto com o código da janela de streaming, tenho o código para os elementos de texto e botão que serão exibidos. Mas no navegador, essas partes desaparecem. Quando abro o Inspetor, esses elementos não existem! Até agora, tentei várias abordagens para evitar essa situação, isolando / incorporando a janela de streaming na guia do navegador. Essas abordagens são: iframe, URI de dados, substituição multipart / x-mixed, formulário. Infelizmente, o mesmo resultado ocorreu em todas essas abordagens (cor de fundo cinza, janela de transmissão no meio da tela e botões e texto desaparecidos).

A única coisa que sei é que, quando o navegador "vê" a imagem recebida do servidor, produz esses efeitos colaterais. Quando eu crio um HTML apenas com texto e botões, ele é exibido perfeitamente. Faço algo errado aqui, mas não consigo encontrar o que é.

Abaixo, anexo 2 fotos do que recebo na guia do navegador e o código HTML que envio do servidor esp-12e para uma captura de foto

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

Janela de vídeo - botões e texto ausentes Código HTML que escrevi para ser atendido pelo servidor esp-12e

Finalmente fiz alguns progressos, mas não 100%. Consegui exibir imagens JPEG no iframe, incorporando dados no formato JPEG a partir de uma imagem com o método URI de dados dentro do elemento Iframe.

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

Meu erro foi não usar as aspas com a ordem correta e os dados da imagem foram interpretados como texto no navegador. Depois tentei fazer o mesmo com a função usada para enviar a imagem capturada da câmera para o navegador. Infelizmente, o mesmo problema surgiu e não posso corrigi-lo desta vez. Algo acontece quando envio uma sequência com várias aspas para o navegador porque ela as interpreta como texto e não como formato de dados jpeg como este: / 9j / 4AAQ ...... Enviei uma foto do inspetor do navegador (mostrando o navegador) dados recebidos quando uso a função para os dados de quadro enviados da câmera) para entender melhor o que quero dizer. Alguma idéia sobre isso?

Os dados são interpretados com defeito devido a várias aspas (?)

Aqui está uma revisão do que concluí até agora.Eu criei um HTML com um Iframe dentro dele e também alguns botões. O iframe e os botões são exibidos corretamente na mesma guia do navegador. Agora, dentro do iframe, coloquei o atributo srcdoc e inseri os dados jpeg brutos diretamente nele (de uma imagem jpeg de amostra), pois eles são codificados (base64), mas o navegador interpretou esses dados jpeg como texto sem formatação e os exibi no iframe como texto. Depois usei a tag image dentro do srcdoc para agrupar os dados jpeg brutos no iframe. Isso funcionou após alguns erros que cometi com as aspas dentro da string iframe. Em seguida, removi os dados jpeg brutos da tag da imagem e os substitui pela função que traz dados jpeg da câmera. Envio a primeira parte da sequência de respostas (abrindo as tags iframe e img), depois envio os dados da câmera e, finalmente, envio a segunda parte da sequência de respostas (fechando as tags iframe e img). Normalmente, ele deve funcionar desde que eu segui o mesmo procedimento de antes. Mas o navegador não conseguiu interpretar a imagem ... novamente.

Abaixo, adicionamos as partes do código da imagem de amostra codificada (que o navegador interpretou como imagem) e, em seguida, a função da câmera (que as interpretou como caracteres estranhos e não como imagem), para comparação. Ambos devem funcionar da mesma maneira, mas apenas os primeiros trabalhos.

Imagem de amostra 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 ";

Função da câmera sendFrame ():

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

Então, acho que descobri o que há de errado com os dados jpeg recebidos da câmera. A função camera traz os dados jpeg (para o servidor e depois para o cliente) em um formato que o navegador interpreta como texto ou algo parecido porque contém caracteres estranhos (verifique a última imagem que publiquei).

Também para escrever o código html, uso aspas "e '(ou" e \') para criar o código iframe e tudo o mais dentro do iframe.

E eis a questão: como alguns dos dados jpeg da câmera são interpretados como citações pelo navegador, eles interagem com as citações que coloquei no iframe para envolver a tag img e os dados provenientes da câmera, e é por isso que estraga tudo no iframe (eu acho)

Existe alguma maneira de converter os dados da imagem provenientes da função da câmera em base64, para que eles não interajam com as aspas das tags iframe e image?

Sparky
fonte
2
É possível incluir um exemplo de código mínimo do problema aqui? Suspeito que, sem isso, qualquer resposta seria apenas especulação. Meu palpite é que talvez você está servindo apenas a imagem, ou servindo-a com o errado Content-Type, como é claramente sendo interpretado como uma imagem (todos os estilos inseridos são estilos internos Firefox )
Aurora0001
A segunda imagem inclui o código, mas enviarei mais um. Obrigado pela ajuda
Sparky
1
Eu estava pensando no código do servidor também, se você o tiver. Você está usando uma biblioteca pré-fabricada como esta ou criou a sua?
Aurora0001
1
Sim, eu li esse código, mas pensei em construí-lo sozinho (para entendê-lo melhor). Vou enviá-lo em um momento #
Sparky
1
Desculpe-me pela resposta atrasada, mas eu estava arrumando um pouco o código para ficar ... legível. Eu tentei métodos diferentes, como mencionei antes. Mas o mesmo resultado ocorreu todas as vezes. Portanto, deve ser outra coisa. Estou um pouco perdido aqui
Sparky

Respostas:

4

Você está escrevendo diretamente da câmera da web os dados no fluxo e, depois disso, vem o modelo de resposta vazio que você está construindo.

Você pode ver, você não escreve a primeira parte da resposta para o wifi e grava dados da câmera diretamente no wifi.

Como seus dados da câmera já têm uma formatação, sugiro adicionar dados ao iframe em vez da tag img, onde estão agora e não pertencem.

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

e onde você verifica a qual URL você respondeu com serveWebpage () que você faz semelhante para corresponder a serveImage () e / yourURIforImage.

mico
fonte
Segui sua opinião e adicionei um client.print (resposta) imediatamente após a primeira parte da resposta e agora posso ver algum progresso. Eu mantive o elemento img para ver o que vai acontecer. O texto e o botão são exibidos corretamente (acho que é um bom sinal), mas os dados da imagem não são interpretados pelo navegador como uma imagem, mas como caracteres estranhos. Por que o navegador não entende os dados da imagem como imagem desde que os converti para base64? Adicionarei um iframe e apago o elemento img para ver o que acontecerá e voltarei #
Sparky
Eu criei uma janela iframe e lá tentei incorporar a imagem tirada da câmera com o método URI de dados. Mas os dados da imagem não são interpretados como imagem pelo navegador e caracteres estranhos são exibidos no iframe. Também usei srcdoc e não src para incorporar os dados da imagem. Alguma ideia?
Sparky
Para fazer este trabalho, escrita pela primeira vez um método que retorna com êxito a imagem somente e, em seguida, em outra chamada de método que o método <iframe src =" caminho para a imagem> </ iframe>
mico
Sim, não é uma má ideia, mas o fato é que usei uma imagem da câmera da seguinte maneira: salvei a imagem JPEG capturada no meu PC, codifiquei-a para base64 e, finalmente, coloquei-a no URI de dados iframe srcdoc para Ser exibido.
Sparky
Também coloquei os dados da imagem diretamente no srcdoc sem a tag da imagem, mas o navegador os interpreta como caracteres. Caracteres estranhos, não apenas letras ou números.
Sparky
3

O que mais se destaca é a sua afirmação:

Algo acontece quando eu envio uma string com várias aspas para o navegador porque as interpreta como texto e não como formato de dados jpeg como este: / 9j / 4AAQ ......

Lembrei-me de que existe uma maneira específica de incorporar aspas é html: é necessário algum tipo de caractere de escape. Eu pesquisei no google

incorporar aspas em html

Esta pergunta foi respondida no StackOverflow aqui:

Como escapar corretamente de aspas dentro de atributos html?

Parece que você tem aspas entre aspas. Portanto, não tenho certeza se você já está usando os caracteres de escape ou não, mas sugiro usar a opção explícita

&quot; 

para suas cotações incorporadas.

grldsndrs
fonte
Vou tentar isso e digo o que aconteceu. & quote é o mesmo que \ "ou '? Se eu usar & quote e \" e' na mesma string em que o navegador os interpretará. Obrigado
Sparky
Não tenho certeza. Mas houve muitos resultados retornados de uma pesquisa no Google. Então, eu apostaria que a resposta a essa pergunta seja encontrada rapidamente, se você fizer a pesquisa.
grldsndrs