2012-02-15 59 views
10

私はwebsockifyを使用して、画像をPythonサーバーからHTML5キャンバスに表示しています。websocket経由で画像を受信

私はPythonサーバーから画像を正常に送信できたと思いますが、キャンバスに画像を表示することはできません。

問題は、キャンバスに表示しようとしているバイト数と関係があり、画像全体が受信され、キャンバスに画像が表示されるまで待っていないと思います。

これまで私は持っていた:

オンメッセージ機能。私は、画像を送ったとき、私はコンソールの12 MESSAGERECEIVED

ws.on('message', function() { 
    //console.log("MESSAGERECEIVED!") 
      msg(ws.rQshiftStr()); 
    }); 

私は文字列を受け取り、私はキャンバス上に表示しようとしていますMSG機能を取得します。私はこの方法を各画像に対して12回呼び出す。スティングのフォーマットは'xÙõKþ°pãüCY次のとおりです。

function msg(str) { 
     //console.log(str); 
     console.log("RELOAD"); 

     var ctx = cv.getContext('2d'); 
     var img = new Image(); 
     //console.log(str); 
     img.src = "data:image/png;base64," + str; 
     img.onload = function() { 
      ctx.drawImage(img,0,0); 
     } 
    } 

この問題を解決する方法上の任意の提案?

+0

クライアントがhybiのドラフトをサポートしていない場合を除き、イメージをbase64としてWebソケット上に送信しないでください。 Base64には33%のオーバーヘッドが発生します。したがって、バイナリとして送信することが望ましい。 – einaros

+0

私は 'websockify'がbase64に転送されたすべてを変換していると思います。 – glarkou

+0

その場合、それはひどいです。別のwebsocket実装を探します。 – einaros

答えて

11

websockify + websock.jsの焦点は、ストリーミングバイナリデータを透過的にサポートすることです(詳細は後述)。受信キューから取得したデータは、すでにbase64でデコードされています。ただし、データURIスキームはbase64でエンコードされた文字列を必要としているため、イメージデータをbase64にエンコードする必要があります。あなたは、base64エンコードバイナリコード化された文字列組み込みwindow.btoa()を使用することができます。

img.src = "data:image/png;base64," + window.btoa(str); 

それとも、効率化のためにあなたからのBase64モジュールを使用することができますを/ base64.jsが含まれていますが、それを渡す必要がありますあなたはrQshiftBytesからになるだろうとして、バイトの配列:

msg(ws.rQshiftBytes()); 

img.src = "data:image/png;base64," + Base64.encode(data); // str -> data 

websockifyでbase64での使用に関して:

websockifyは悲惨なバイナリデータをサポートしていないブラウザをサポートするためにデータをエンコードするためにBASE64を使用していますctly。 iOS SafariやデスクトップSafariなどの人気のあるHixieのみのブラウザに加えて、野生の一部のブラウザバージョンではHyBiを使用していますが、バイナリサポートはありません。残念ながら、Chromeの場合、同じ時間にWebIDLバグがあり、接続を行う前にバイナリサポートを検出できませんでした。

また、Opera、Firefox 3.6-5、IE 8,9でWebSocketを使用する主なオプションはweb-socket-jsです。 web-socket-jsはHyBiをサポートしていますが、バイナリをサポートしておらず、ターゲットとする古いブラウザのほとんどがネイティブバイナリタイプ(Blob型と型付き配列)をサポートしていないためおそらくないでしょう。

HyBiとバイナリデータをサポートするブラウザの市場シェアは現在かなり低いです。ただし、Websockifyは、ブラウザがバイナリデータをサポートしていて、base64エンコード/デコードを必要とせずに直接サポートを使用するかどうかを、オブジェクト検出またはブラウザのバージョン検出によって検出します。

base64エンコード/デコードのレイテンシ(およびCPU)オーバーヘッドはかなり低く、通常ネットワークの待ち時間によって洗い流されません。 base64でエンコードされたデータの帯域幅オーバーヘッドは約25%です(つまり、生データが33%大きくなります)が、WebSocket経由では基本的にすべてのブラウザのバイナリデータを提供します(web-socket-js polyfill/shim必要に応じてWebsockifyによって透過的に使用されます)。

+0

詳細な結果をもう一度お寄せいただきありがとうございます。画像が完全に転送されたかどうかを判断する方法の例を教えてください。より具体的には、私は、バッファーサイズ1024の標準的なソケットを使用してデータを送信するPythonで具体的に。私はバッファよりも大きい画像を持っている場合は1024の部分で送信されます。 12kbの画像)websocketメッセージイベント。これらのメッセージをすべて組み合わせてイメージを再構築するにはどうすればよいですか?もう一度ありがとう。 – glarkou

+0

WebSocketServer.send_frames(bufs)は "バッファ"のリストを取ります。各バッファは、クライアント(ブラウザ)に単一のメッセージ(1回のメッセージの着信)として配信されます。あなたがonmessageの受信待ち行列から全てをシフトすると、メッセージ全体が得られます。より小さなチャンクでsend_framesを呼び出す場合(またはsend_framesを完全にバイパスする場合)、メッセージをリフレーミングする(つまり、各メッセージ/イメージの前に長さプレフィックスを追加する)ためのメカニズムをプロトコルに追加する必要があります。しかしこれはWebSocketの機能を複製しているので、メッセージ/画像全体でsend_framesを使うことをお勧めします。 – kanaka

+0

残念ながら、私はそれを行う方法を理解できません。現時点では、私はPythonサーバーが 'Server 1'で画像を送信しており、' Server 2 'で 'websockify'を実行しています。私が 'var arr = ws.rQshiftBytes(ws.rQlen())、str =" "、chr;を実行しようとしたメッセージを受け取ったとき、 \t \t \t \t \t \t \t \t一方(arr.length> 0){ \t \t \t \t \t CHR = arr.shift()。 \t \t \t \t \t str + = String.fromCharCode(chr); \t \t \t \t \t} \t \t \t \t //console.log(str)。 msg(文字列); '残念ながら。 'ws.on( 'message'、function()'はサーバから送られたすべてのバッファに対して呼び出されるので、キャンバス上に描画する準備ができているかどうか判断できません。 – glarkou

関連する問題