ESP12-Eビデオストリーミングウィンドウ、テキストおよびボタンが期待どおりに表示されない


8

ESP8266(12-E)モジュールに接続されたarducam mini 2MPカメラを使用していて、テキストとコントロールボタンが周囲にあるウィンドウ内に、すべて同じブラウザータブ/ページにビデオストリーミングを実装しようとしています。サーバーで使用する2つのHTMLページを作成しました。1つ目は、画像ストリーミングのないホームWebページで、テキストボタンといくつかのCSSを備えた単純なページです。2番目のHTMLページは、連続するフレーム(ストリーミングビデオ)といくつかのテキストおよびボタンをブラウザーに提供します。ホームページがブラウザに送信されると、すべてが期待どおりに表示されます。しかし、2番目のHTML Webページが提供されているが、ブラウザー(FirefoxまたはChrome)がサーバー(esp12-e)からの応答を受信すると、奇妙なことが発生します。

通常、私は小さなウィンドウにカメラから取得した連続フレームを表示し、そのウィンドウ上にテキストとその下にいくつかのコントロールボタンを表示することを期待します。しかし、その代わりに2つのことが起こります。

  1. ブラウザのタブにはビデオストリーミングウィンドウのみが表示されますが、このウィンドウの周りには灰色の背景色しかありません。ボタンなし、テキストなし。「インスペクタ」の「ヘッド」の内側を開くと、背景の灰色を作成する数行のHTMLコードと、サーバーで記述していないCSS要素がいくつかあります。どういうわけか、ブラウザはこのコード行を自動的に作成し、私のオリジナルのHTMLコードに追加します。
  2. 私の元のHTMLコードでは、「body」内に、ストリーミングウィンドウのコードとともに、表示されるテキスト要素とボタン要素のコードがあります。しかし、ブラウザでは、これらの部分は消えます。インスペクターを開くと、これらの要素は存在しません!これまでに、ブラウザのタブ内にストリーミングウィンドウを分離/埋め込むことで、この状況を回避するためにさまざまなアプローチを試みてきました。これらのアプローチは、iframe、データURI、multipart / x-mixed replace、formです。残念ながら、これらすべてのアプローチで同じ結果が発生しました(灰色の背景色、画面中央のストリーミングウィンドウ、表示されていないボタンとテキスト)。

私が知っている唯一のことは、ブラウザがサーバーからの着信画像を「見る」と、これらの副作用が生じることです。テキストとボタンのみのHTMLを作成すると、うまく表示されます。私はここで何か悪いことをしていますが、それが何であるかを見つけることができません。

以下に、ブラウザーのタブで取得したものの2つの写真と、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);  
}  

ビデオWindow_missingボタンとテキスト サーバーesp-12eによって提供されるように記述したHTMLコード

ようやく少し進歩しましたが、100%ではありません。iframe要素内にデータURIメソッドを含む画像からjpeg形式のデータを埋め込むことにより、iframeにjpeg画像を表示することができました。

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

私の間違いは、正しい順序で引用符を使用せず、画像データがブラウザーでテキストとして解釈されることでした。次に、キャプチャした画像をカメラからブラウザーに送信するために使用する関数を使用して、同じことを試みました。残念ながら、同じ問題が発生し、今回は修正できません。次のように、jpegデータ形式ではなくテキストとして解釈されるため、複数の引用符を含む文字列をブラウザに送信すると、何かが起こります。/ 9j / 4AAQ ......ブラウザのインス​​ペクタから画像をアップロードしました(ブラウザのカメラの送信フレームデータの関数を使用したときに受信したデータ)が意味を理解しやすくします。これに関するアイデアはありますか?

複数の引用符(?)が原因でデータが誤って解釈される

ここに私がこれまでに完了したことのレビューがあります。内部にiframeといくつかのボタンを含むHTMLを作成しました。iframeとボタンの両方が同じブラウザーのタブに正しく表示されます。ここで、iframe内にsrcdoc属性を置き、そこに生のjpegデータを直接(サンプルjpeg画像の)挿入しました(base64)が、ブラウザーはこれらのjpegデータをプレーンテキストとして解釈し、iframeにテキストとして表示しました。次に、srcdoc内のイメージタグを使用して、未加工のjpegデータをiframeにラップしました。これは、iframe文字列内の引用符で行ったいくつかのミスの後に機能しました。次に、画像タグから未加工のjpegデータを削除し、カメラからjpegデータを取り込む機能に置き換えました。応答文字列の最初の部分(iframeとimgタグを開く)を送信します。次に、カメラからデータを送信し、最後に応答文字列の2番目の部分(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データに問題があることを見つけたと思います奇妙な文字(私が投稿した最後の画像を確認してください)。

また、htmlコードを記述するために、引用符 "および '(または"および\')を使用して、iframeコードおよびその他すべてをiframe内に作成します。

そして、これが問題です:カメラのjpegデータの一部はブラウザーによって引用として解釈されるため、imgタグとカメラからのデータをラップするためにiframe内に置いた引用と相互作用し、それがすべてを台無しにしてしまう理由ですiframeで(私は思う)

とにかく、カメラ機能からの画像データをbase64に変換して、iframeタグと画像タグのラッピング引用符と相互作用しないようにしますか?


2
ここに問題の最小限のコード例を含めることは可能ですか?それがなければ、どんな答えも推測に過ぎないと思う。私の推測では、多分あなたは画像のみにサービスを提供する、または間違ったでそれを提供していることであるContent-Typeことが明確にイメージとして解釈されていて(すべての挿入のスタイルがあり、内部Firefoxのスタイル
Aurora0001

2番目の画像にはコードが含まれていますが、もう1つアップロードします。助けてくれてありがとう
Sparky

1
もしあれば、私もサーバーコードを考えていました。このような既製のライブラリを使用していますか、それとも自分で作成しましたか?
Aurora0001

1
はい、そのコードを読みましたが、自分で作成することを考えました(理解を深めるため)。すぐにアップロードします
Sparky

1
回答が遅れて申し訳ありませんが、読みやすいようにコードを少し整理していました。前に述べたように、私はさまざまな方法を試しました。しかし、同じ結果が毎回発生しました。だからそれは何か別のものでなければならない。私はここで少し迷っています
Sparky 2017

回答:


4

Webカメラからデータをストリームに直接書き込み、その後、作成する空の応答テンプレートが続きます。

ご覧のとおり、答えの最初の部分はwifiに書き込まず、カメラからデータを直接wifiに書き込みます。

カメラからのデータにはすでにフォーマットが設定されているため、imgタグの代わりにiframeにデータを追加することをお勧めします。

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)を1つ追加しました。何が起こるかを確認するために、img要素を保持しました。テキストとボタンは正しく表示されますが(これは良い兆候だと思います)、画像データはブラウザーによって画像として解釈されず、奇妙な文字です。データをbase64に変換したため、ブラウザが画像データを画像として認識しないのはなぜですか?iframeを追加してimg要素を消去し、何が起こるかを確認して、また戻ってきます
Sparky

iframeウィンドウを作成し、そこにカメラから取得した画像をデータURIメソッドで埋め込もうとしました。しかし、画像データはブラウザによって画像として解釈されず、奇妙な文字がiframe内に表示されます。また、画像データを埋め込むためにsrcではなくsrcdocを使用しました。何か案は?
Sparky 2017

これを機能させるには、まず画像のみを正常に返すメソッドを記述し、次に別のメソッド呼び出しでそのメソッドを呼び出します<iframe src = "画像へのパス> </ iframe>
mico

はい、それは悪い考えではありませんが、問題はカメラの画像を次のように使用したことです:キャプチャしたJPEG画像をPCに保存してから、base64にエンコードし、最後にiframe srcdocデータURIに入れました。表示されます。
Sparky 2017

また、画像タグを付けずに画像データを直接srcdoc内に配置しましたが、ブラウザはそれらを文字として解釈します。文字や数字だけでなく、奇妙な文字。
Sparky 2017

3

目立つのはあなたの声明です:

複数の引用符を含む文字列をブラウザに送信すると、次のようなjpegデータ形式ではなくテキストとして解釈されるため、何かが発生します。/ 9j / 4AAQ ......

引用符を埋め込む特定の方法がhtmlであることを思い出しました。ある種のエスケープ文字が必要です。私はググった

引用符をHTMLに埋め込む

この質問はStackOverflowでここに答えられました:

HTML属性内の引用を適切にエスケープする方法は?

引用符が引用符で囲まれているようです。したがって、エスケープ文字をすでに使用しているかどうかはわかりませんが、明示的なオプションを使用することをお勧めします

&quot; 

あなたの埋め込まれた引用のために。


私はこれを試してみて、何が起こったのかを教えます。&quoteは\ "または 'と同じですか?&quoteと\"および'を同じ文字列で使用すると、ブラウザはそれらをどのように解釈しますか。ありがとう
Sparky 2017

わからない。しかし、Google検索から返された多くの結果がありました。だから、もしあなたが検索をすれば、その質問への答えがすぐに見つかるはずです。
grldsndrs 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.