2012-02-15 28 views
10

Estoy usando websockify para mostrar imágenes de un servidor python a un lienzo HTML5.Recepción de imágenes a través de websocket

Creo que he logrado enviar imágenes de mi servidor de Python con éxito, pero no puedo mostrar las imágenes en mi lienzo.

Creo que el problema tiene que ver con el número de bytes que estoy tratando de mostrar en el lienzo y creo que no estoy esperando hasta que se reciba toda la imagen y luego mostrar la imagen en el lienzo.

Hasta ahora tengo:

El mensaje de función. Cuando envié una imagen que reciben un 12 MESSAGERECEIVED en la consola

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

La función msg donde recibo la cadena y yo estoy tratando de mostrarlo en la lona. Invoco el método 12 veces para cada imagen. El formato de la picadura es '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); 
     } 
    } 

¿Alguna sugerencia sobre cómo solucionar este problema?

+0

No debe transmitir imágenes como base64 sobre websockets a menos que el cliente no admita los borradores hybi. Base64 incurrirá en un 33% de gastos generales. El envío como binario es por lo tanto preferible. – einaros

+0

Creo que 'websockify' está convirtiendo todo lo transferido a base64. – glarkou

+0

Si ese es el caso, eso es terrible. Busque otra implementación de websocket. – einaros

Respuesta

11

El objetivo de websockify + websock.js es la compatibilidad transparente con la transmisión de datos binarios (más información sobre esto a continuación). Los datos que obtiene de la cola de recepción ya están decodificados en base64. Sin embargo, el esquema de URI de datos espera una cadena codificada en base64, por lo que debe codificar los datos de imagen en base64. Se puede utilizar el window.btoa orden interna() para codificar base 64 un binario codificado cadena:

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

O, para una mayor eficiencia se puede utilizar el módulo de base 64 de include/base64.js pero tendrá que pasar una matriz de bytes como su obtendría de rQshiftBytes:

msg(ws.rQshiftBytes()); 

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

Respecto al uso de base 64 en websockify:

websockify utiliza base 64 para codificar los datos para soportar los navegadores que no soportan datos binarios grave ctly. Además de los navegadores Hixie tan populares como iOS Safari y Safari de escritorio, algunas versiones de navegadores en la naturaleza usan HyBi pero faltan soporte binario. Y desafortunadamente, en el caso de Chrome, también tenían un error WebIDL alrededor del mismo tiempo, lo que impide detectar el soporte binario antes de hacer una conexión.

Además, la opción principal para usar WebSockets en Opera, Firefox 3.6-5, IE 8 y 9 es web-socket-js. web-socket-js admite HyBi pero no tiene soporte binario y probablemente no lo hará porque la mayoría de los navegadores antiguos a los que apunta no son compatibles con los tipos binarios nativos (blob y matrices tipadas).

La cuota de mercado de los navegadores que admiten HyBi y datos binarios es actualmente bastante baja. Sin embargo, en el futuro, Websockify detectará (ya sea mediante la detección de objetos o la detección de la versión del navegador) si el navegador admite datos binarios y utiliza ese soporte directamente sin la necesidad de codificar/descodificar base64.

La sobrecarga de latencia (y CPU) de la codificación/decodificación de base64 es bastante baja y, en general, se ve arrastrada por las latencias de la red. La sobrecarga de ancho de banda de los datos codificados en base64 es de aproximadamente el 25% (es decir, los datos sin procesar se vuelven un 33% mayores), pero proporciona datos binarios sobre WebSockets en prácticamente todos los navegadores (con el webfill-js polyfill/shim que es utilizado de forma transparente por websockify si es necesario).

+0

Gracias por el resultado detallado una vez más. ¿Puedes dar un ejemplo de cómo puedo determinar si una imagen se transfiere por completo? Más específicamente, en Python envío los datos usando un socket regular con un buffer de tamaño 1024. Si tengo una imagen que es más grande que el buffer entonces será enviada en partes de 1024. En el navegador esto se disparará 12 veces (si tengo una imagen de 12kb) el evento de mensaje websocket. ¿Cómo puedo combinar todos estos mensajes para reconstruir la imagen? Gracias una vez más. – glarkou

+0

WebSocketServer.send_frames (bufs) toma una lista de "búferes". Cada memoria intermedia se entregará al cliente (navegador) como un mensaje único (un mensaje de advertencia de un mensaje). Si desactiva el todo de la cola de recepción en onmesage, recibirá mensajes completos. Si está llamando a send_frames con fragmentos más pequeños (o pasando por alto send_frames por completo), necesitará agregar a su protocolo algún mecanismo para reformular los mensajes (es decir, agregar un prefijo de longitud antes de cada mensaje/imagen). Pero esto es la duplicación de la funcionalidad WebSocket, por lo que sugiero usar send_frames con mensajes/imágenes completos. – kanaka

+0

Lamentablemente, no puedo entender cómo hacerlo. Por el momento tengo un servidor de python enviando imágenes en 'Server 1' y tengo' websockify' ejecutándose en 'Server 2'. Cuando recibo los mensajes, traté de hacer 'var arr = ws.rQshiftBytes (ws.rQlen()), str =" ", chr; \t \t \t \t \t \t \t \t mientras (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 (str); 'Desafortunadamente. 'ws.on ('message', function()' se invoca para cada buffer enviado desde el servidor, por lo que no puedo determinar cuando una imagen está lista para dibujarlo en canvas. – glarkou

Cuestiones relacionadas