2012-02-15 26 views
10

Używam websockify do wyświetlania obrazów z serwera Pythona na płótnie HTML5.Odbieranie obrazu za pośrednictwem websocket

Myślę, że udało mi się pomyślnie wysłać obrazy z mojego serwera Pythona, ale nie jestem w stanie wyświetlić obrazów na moim płótnie.

Myślę, że problem dotyczy liczby bajtów, które próbuję wyświetlić na płótnie i uważam, że nie czekam, aż cały obraz zostanie odebrany, a następnie wyświetlenie obrazu na płótnie.

Do tej pory posiadam:

Funkcja wiadomości. Kiedy wysłałem obraz mam 12 MESSAGERECEIVED w konsoli

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

Funkcją msg gdzie mogę otrzymać ciąg i próbuję wyświetlić go na płótnie. Wywołuję metodę 12 razy dla każdego zdjęcia. Format użądleniu jest '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); 
     } 
    } 

Wszelkie sugestie, w jaki sposób rozwiązać ten problem?

+0

Nie należy przesyłać obrazów jako base64 na stronach internetowych, chyba że klient nie obsługuje projektów hybi. Base64 poniesie 33% narzutów. Dlatego preferowane jest wysyłanie jako binarne. – einaros

+0

Myślę, że 'websockify' konwertuje wszystko, co jest przez nią przekazywane, na base64. – glarkou

+0

Jeśli tak jest, to jest okropne. Poszukaj kolejnej implementacji websocket. – einaros

Odpowiedz

11

Głównym celem websockify + websock.js jest przezroczysta obsługa przesyłania strumieniowego danych binarnych (więcej informacji poniżej). Dane, które odbierasz z kolejki odbiorczej, są już dekodowane w base64. Jednak schemat URI danych oczekuje ciągu zakodowanego w base64, więc musisz zakodować dane obrazu na base64. Można użyć wbudowanego window.btoa() do base64 zakodować binarny zakodowany ciąg:

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

Albo, dla większej wydajności można użyć modułu Base64 z include/base64.js ale trzeba zdać z niego tablica bajtów jak twoje dostanie od rQshiftBytes:

msg(ws.rQshiftBytes()); 

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

Odnośnie stosowania base64 w websockify:

websockify używa base64 do kodowania danych w celu wsparcia przeglądarek, które nie obsługują dane binarne dire Ctly. Poza popularnymi przeglądarkami Hixie, takimi jak Safari na iOS i Safari na komputery, niektóre wersje przeglądarek w dziale HyBi używają jedynie obsługi binarnej. I niestety, w przypadku Chrome, mieli też w tym samym czasie błąd WebIDL, który uniemożliwił wykrycie obsługi binarnej przed nawiązaniem połączenia.

Podstawową opcją korzystania z WebSockets w Operze, firefox 3.6-5, IE 8 i 9 jest web-socket-js. web-socket-js obsługuje HyBi, ale nie obsługuje binarnie i prawdopodobnie nie, ponieważ większość starszych przeglądarek, które są w nim ustawione, nie obsługuje natywnych typów binarnych (Blob i Typed Arrays).

Udział w rynku przeglądarek obsługujących HyBi i dane binarne jest obecnie dość niski. Jednak w przyszłości Websockify wykryje (zarówno poprzez wykrywanie obiektów, jak i wykrywanie wersji przeglądarki), czy przeglądarka obsługuje dane binarne i używa tego wsparcia bezpośrednio, bez potrzeby kodowania/dekodowania base64.

Narzut opóźnienia (i procesora) na kodowanie/dekodowanie base64 jest dość niski i zazwyczaj jest wymywany przez sieciowe opóźnienia. Obciążenie przepustowości dla danych zakodowanych w base64 wynosi około 25% (tj. Surowe dane stają się o 33% większe), ale daje dane binarne za pośrednictwem WebSockets w zasadzie na wszystkich przeglądarkach w środowisku naturalnym (za pomocą programu web-socket-js polyfill/shim, który jest używane w przejrzysty sposób przez websockify w razie potrzeby).

+0

Dziękujemy za szczegółowy wynik jeszcze raz. Czy możesz podać przykład, w jaki sposób mogę określić, czy obraz jest w pełni przesłany? Dokładniej w pythonie wysyłam dane za pomocą zwykłego gniazda z rozmiarem bufora 1024. Jeśli mam obraz większy niż bufor, to zostanie wysłany w częściach 1024. W przeglądarce będzie to powodować 12-krotne (jeśli mam obraz o wielkości 12 kB) zdarzenia wiadomości websocket. Jak mogę połączyć wszystkie te wiadomości, aby odbudować obraz? Jeszcze raz dziękuję. – glarkou

+0

WebSocketServer.send_frames (bufs) pobiera listę "buforów". Każdy bufor zostanie dostarczony do klienta (przeglądarki) jako pojedyncza wiadomość (jeden ogień z wiadomości). Jeśli przestawisz wszystko z kolejki odbiorczej w wiadomości, otrzymasz całe wiadomości. Jeśli wywołujesz send_frames z mniejszymi porcjami (lub całkowicie pomijając send_frames), będziesz musiał dodać do swojego protokołu jakiś mechanizm przeformułowania komunikatów (tj. Dodanie przed każdą wiadomością/obrazem prefiksu długości). Jest to jednak powielanie funkcjonalności WebSocket, dlatego sugeruję użycie send_frames z całymi wiadomościami/obrazami. – kanaka

+0

Niestety, nie mogę zrozumieć, jak to zrobić. W tej chwili mam serwer Pythona wysyłający obrazy na 'Server 1' i mam' websockify' działający na 'Server 2'. Po otrzymaniu wiadomości próbowałem wykonać polecenie 'var arr = ws.rQshiftBytes (ws.rQlen()), str =" ", chr; \t \t \t \t \t \t \t \t while (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); 'Niestety. 'ws.on ('message', function()' jest wywoływane dla każdego bufora wysyłanego z serwera, więc nie jestem w stanie określić, kiedy obrazek jest gotowy, aby narysować go na płótnie – glarkou

Powiązane problemy