La fenêtre de diffusion vidéo ESP12-E, le texte et les boutons ne s'affichent pas comme prévu

8

J'ai une caméra arducam mini 2MP connectée à un module ESP8266 (12-E) et j'essaie d'implémenter le streaming vidéo à l'intérieur d'une fenêtre avec du texte et des boutons de contrôle autour, le tout dans le même onglet / page de navigateur. J'ai créé deux pages HTML à utiliser par le serveur. La première est la page Web d'accueil sans streaming d'images, juste une simple page avec des boutons de texte et du CSS. La deuxième page HTML sert les images continues (streaming vidéo) ainsi que du texte et des boutons au navigateur. Lorsque la page d'accueil est envoyée au navigateur, tout s'affiche comme je m'y attendais. Mais, lorsque la deuxième page Web HTML est servie, mais des choses étranges se produisent lorsque le navigateur (Firefox ou Chrome) reçoit la réponse du serveur (esp12-e).

Normalement, je m'attendrais à une petite fenêtre affichant des images continues prises de l'appareil photo avec du texte sur cette fenêtre et des boutons de contrôle en dessous. Mais, au lieu de cela, deux choses se produisent.

  1. Seule la fenêtre de streaming vidéo s'affiche dans l'onglet du navigateur mais autour de cette fenêtre il n'y a qu'une couleur de fond grise. Pas de boutons, pas de texte. Lorsque j'ouvre l'inspecteur HTML, à l'intérieur de "head", il y a quelques lignes de code HTML qui créent la couleur grise d'arrière-plan et des trucs CSS que je n'ai pas écrits sur mon serveur. D'une manière ou d'une autre, le navigateur crée automatiquement ces lignes de code et les ajoute dans mon code HTML d'origine.
  2. Dans mon code HTML d'origine, à l'intérieur de "body", avec le code de la fenêtre de streaming, j'ai le code pour le texte et les éléments de bouton qui seront affichés. Mais dans le navigateur, ces parties disparaissent. Lorsque j'ouvre l'inspecteur, ces éléments n'existent pas! Jusqu'à présent, j'ai essayé différentes approches pour éviter cette situation en isolant / incorporant la fenêtre de streaming dans l'onglet du navigateur. Ces approches sont: iframe, données URI, multipart / x-mixed replace, form. Malheureusement, le même résultat s'est produit pour toutes ces approches (couleur de fond gris, fenêtre de streaming au milieu de l'écran et boutons et texte disparus).

La seule chose que je sais, c'est que lorsque le navigateur "voit" l'image entrante du serveur, il produit ces effets secondaires. Lorsque je crée un HTML uniquement avec du texte et des boutons, il s'affiche très bien. Je fais quelque chose de mal ici mais je ne trouve pas ce que c'est.

Ci-dessous, je joins 2 photos de ce que j'obtiens dans l'onglet du navigateur et le code HTML que j'envoie du serveur esp-12e pour une capture photo

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

Fenêtre vidéo_ boutons et texte manquants Code HTML que j'ai écrit pour être servi par le serveur esp-12e

J'ai finalement fait quelques progrès mais pas à 100%. J'ai réussi à afficher des images jpeg dans l'iframe en incorporant des données au format jpeg à partir d'une image avec la méthode URI de données à l'intérieur de l'élément Iframe.

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

Mon erreur est que je n'ai pas utilisé les guillemets dans le bon ordre et les données d'image ont été interprétées comme du texte dans le navigateur. J'ai ensuite essayé de faire la même chose avec la fonction que j'utilise pour envoyer l'image capturée de l'appareil photo vers le navigateur. Malheureusement, le même problème s'est posé et je ne peux pas le résoudre cette fois. Quelque chose se produit lorsque j'envoie une chaîne avec plusieurs guillemets au navigateur car elle les interprète comme du texte et non comme un format de données jpeg comme ceci: / 9j / 4AAQ ...... J'ai téléchargé une photo de l'inspecteur de mon navigateur (montrant le navigateur reçu des données lorsque j'utilise la fonction pour les données de trame envoyées par l'appareil photo) pour comprendre plus facilement ce que je veux dire. Des idées à ce sujet?

Les données sont interprétées comme erronées en raison de plusieurs citations (?)

Voici un examen de ce que j'ai accompli jusqu'à présent.J'ai créé un HTML avec un Iframe à l'intérieur et aussi quelques boutons. L'iframe et les boutons sont affichés correctement dans l'onglet du même navigateur. Maintenant, à l'intérieur de l'iframe, j'ai mis l'attribut srcdoc et inséré les données JPEG brutes directement dedans (d'un exemple d'image JPEG) car elles sont encodées (base64) mais le navigateur a interprété ces données JPEG en texte brut et les a affichées dans l'iframe en tant que texte. Ensuite, j'ai utilisé la balise image dans srcdoc pour envelopper les données JPEG brutes dans l'iframe. Cela a fonctionné après quelques erreurs que j'ai faites avec les guillemets dans la chaîne iframe. Ensuite, j'ai supprimé les données jpeg brutes de la balise d'image et les ai remplacées par la fonction qui apporte les données jpeg de la caméra. J'envoie la première partie de la chaîne de réponse (ouverture des tags iframe et img), puis j'envoie les données de la caméra et enfin j'envoie la deuxième partie de la chaîne de réponse (fermeture des balises iframe et img). Normalement, cela devrait fonctionner puisque j'ai suivi la même procédure que précédemment. Mais le navigateur n'a pas pu interpréter l'image ... à nouveau.

Ci-dessous, j'ai ajouté les parties de code pour l'échantillon d'image codé (que le navigateur a interprété comme image), puis la fonction appareil photo (qui les a interprétées comme des caractères impairs et non comme une image), à ​​titre de comparaison. Les deux devraient fonctionner de la même manière mais seulement les premiers travaux.

Exemple d'image codée:

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

Fonction appareil photo sendFrame ():

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

Donc, je pense que j'ai trouvé ce qui se passe mal avec les données jpeg entrants de l'appareil photo La fonction de la caméra apporte les données jpeg (au serveur, puis au client) dans un format que les interprète du navigateur sous forme de texte ou quelque chose comme ça parce qu'il contient personnages étranges (vérifiez la dernière image que j'ai postée).

Aussi pour écrire le code html j'utilise des guillemets "et '(ou" et \') pour créer le code iframe et tout le reste à l'intérieur iframe.

Et voici la chose: parce que certaines données jpeg de l'appareil photo sont interprétées comme des citations par le navigateur, elles interagissent avec les citations que je mets à l'intérieur d'iframe pour envelopper la balise img et les données provenant de la caméra et c'est pourquoi cela gâche tout dans iframe (je pense)

Est-il possible de convertir les données d'image provenant de la fonction appareil photo en base64, afin qu'elles n'interagissent pas avec les guillemets enveloppants des balises iframe et image?

Sparky
la source
2
Est-il possible pour vous d'inclure ici un exemple de code minimal du problème? Je soupçonne que sans cela, toute réponse ne serait que spéculation. Je suppose que peut-être que vous ne servez que l'image, ou que vous la Content-Type
dessinez
La deuxième image comprend le code mais j'en mettrai une de plus. Merci pour l'aide
Sparky
1
Je pensais aussi au code serveur, si vous l'avez. Utilisez-vous une bibliothèque prédéfinie comme celle-ci ou avez-vous lancé la vôtre?
Aurora0001
1
Oui j'ai lu ce code mais j'ai pensé à le construire moi-même (pour mieux le comprendre). Je vais le télécharger dans un instant
Sparky
1
Excusez-moi pour la réponse différée mais je rangeais un peu le code pour être ... lisible. J'ai essayé différentes méthodes comme je l'ai mentionné précédemment. Mais le même résultat s'est produit à chaque fois. Donc ça doit être autre chose. Je suis un peu perdu ici
Sparky

Réponses:

4

Vous écrivez directement à partir de votre caméra Web les données dans le flux et après cela vient le modèle de réponse vide que vous construisez.

Vous pouvez voir, vous n'écrivez pas la première partie de la réponse au wifi et vous écrivez les données de la caméra directement au wifi.

Parce que vos données de la caméra ont déjà un formatage, je suggère d'ajouter des données à iframe au lieu de la balise img, où elles se trouvent maintenant et n'appartiennent pas.

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

et où vous vérifiez à quel uri vous avez répondu avec serveWebpage () que vous faites similaire pour correspondre à serveImage () et / yourURIforImage.

mico
la source
J'ai suivi votre opinion et j'ai ajouté un client.print (réponse) immédiatement après la première partie de la réponse et maintenant je peux voir des progrès. J'ai gardé l'élément img pour voir ce qui va se passer. Le texte et le bouton sont affichés correctement (c'est un bon signe je pense) mais les données d'image ne sont pas interprétées par le navigateur comme une image, mais des caractères étranges. Pourquoi le navigateur ne comprend pas les données d'image en tant qu'image depuis que j'ai converti les données en base64? Je vais ajouter un iframe et effacer l'élément img pour voir ce qui va se passer et je serai de retour
Sparky
J'ai créé une fenêtre iframe et là j'ai essayé d'incorporer l'image prise depuis la caméra avec la méthode URI de données. Mais les données d'image ne sont pas interprétées comme des images par le navigateur et des caractères étranges sont affichés à l'intérieur de l'iframe. J'ai également utilisé srcdoc et non src pour intégrer les données d'image. Des idées?
Sparky
Pour que cela fonctionne, écrivez d'abord une méthode qui renvoie correctement l'image uniquement, puis dans une autre méthode, appelez cette méthode <iframe src = "chemin d'accès à l'image> </ iframe>
mico
Oui, ce n'est pas une mauvaise idée, mais le problème est que j'ai utilisé une image de la caméra de la manière suivante: j'ai enregistré l'image JPEG capturée dans mon PC, puis je l'ai encodée en base64 et enfin je l'ai mise dans l'URI de données iframe srcdoc pour être affichée.
Sparky
J'ai également mis les données d'image directement dans srcdoc sans balise d'image, mais le navigateur les interprète comme des caractères. Les caractères étranges ne sont pas seulement des lettres ou des chiffres.
Sparky
3

La chose qui ressort est votre déclaration:

Quelque chose se produit lorsque j'envoie une chaîne avec plusieurs guillemets au navigateur car il les interprète comme du texte et non comme un format de données jpeg comme ceci: / 9j / 4AAQ ......

Je me suis souvenu qu'il existe un moyen spécifique d'incorporer des guillemets est le HTML: une sorte de caractères d'échappement est nécessaire. J'ai googlé

intégrer des citations en html

Cette question a été répondue sur StackOverflow ici:

Comment échapper correctement les guillemets à l'intérieur des attributs html?

Il semble que vous ayez des guillemets entre guillemets. Je ne sais donc pas si vous utilisez déjà ou non les caractères d'échappement, mais je suggérerais d'utiliser l'option explicite

&quot; 

pour vos devis intégrés.

grldsndrs
la source
Je vais essayer ça et je vous raconte ce qui s'est passé. & quote est identique à \ "ou '? Si j'utilise & quote et \" et' dans la même chaîne comment le navigateur va les interpréter. Merci
Sparky
Pas certain. Mais de nombreux résultats sont revenus d'une recherche Google. Je parierais donc que la réponse à cette question sera trouvée rapidement, si vous faites la recherche.
grldsndrs