2012-01-06 16 views
17

Mam problemy z przesyłaniem danych MP3 przez WebSocket za pomocą node.js i socket.io. Wszystko wydaje się działać, ale dekodeAudioData nie gra ze mną fair.Jak przesyłać strumieniowo dane MP3 przez WebSockets za pomocą node.js i socket.io?

To jest mój serwer zabawki:

var app = require('http').createServer(handler) 
    , io = require('socket.io').listen(app) 
    , fs = require('fs') 

app.listen(8081); 

function handler (req, res) { 
    res.writeHead(200, { 
     'Content-Type': 'text/html', 
    }); 
    res.end('Hello, world!'); 
} 

io.configure('development', function() { 
    io.set('log level', 1); 

    io.set('transports', [ 'websocket' ]); 
}); 

io.sockets.on('connection', function (socket) { 
    console.log('connection established'); 

    var readStream = fs.createReadStream("test.mp3", 
             {'flags': 'r', 
              'encoding': 'binary', 
              'mode': 0666, 
              'bufferSize': 64 * 1024}); 
    readStream.on('data', function(data) { 
     console.log(typeof data); 
     console.log('sending chunk of data') 
     socket.send(data); 
    }); 

    socket.on('disconnect', function() { 
     console.log('connection droped'); 
    }); 
}); 

console.log('Server running at http://127.0.0.1:8081/'); 

Klient otrzymuje dane jako typu string ale chcę karmić danych do decodeAudioData i wydaje się, że nie lubi sznurki. Wezwanie do decodeAudioData skutkuje następującym komunikatem o błędzie:

Uncaught Error: SYNTAX_ERR: DOM Exception 12 

myślę decodeAudioData potrzebuje danych przechowywanych w ArrayBuffer. Czy istnieje sposób na konwersję danych?

Jest to kod klienta:

<script src="http://127.0.0.1:8081/socket.io/socket.io.js"></script> 
<script> 
    var audioBuffer = null; 
    var context = null; 
    window.addEventListener('load', init, false); 
    function init() { 
     try { 
      context = new webkitAudioContext(); 
     } catch(e) { 
      alert('Web Audio API is not supported in this browser'); 
     } 
    } 

    function decodeHandler(buffer) { 
     console.log(data); 
    } 

    var socket = io.connect('http://127.0.0.1:8081'); 
    socket.on('message', function (data) { 
      // HERE IS THE PROBLEM 
     context.decodeAudioData(data, decodeHandler, function(e) { console.log(e); }); 
    }); 
</script> 
+0

masz znalazł rozwiązanie tego problemu? – codeAnand

+0

Nie znalazłem rozwiązania przy użyciu pliku socket.io. Zobacz moją własną odpowiedź na rozwiązanie bez socket.io. –

+0

Socket.io 1.0 mają wsparcie dla binarnego, próbuję go, ale nie działa. Próbuję też z websocket, ale z dokładnie tym samym błędem. Masz przykład tego, jak to rozwiązujesz ?. – cmarrero01

Odpowiedz

10

Znalazłem sposób na strumień danych MP3 poprzez WebSockets siebie.

Jednym z problemów był rozmiar porcji danych MP3. Wygląda na to, że interfejs Web Audio API musi być zasilany prawidłowymi fragmentami MP3, aby móc dekodować dane. Prawdopodobnie nie jest to zaskakujące. W mojej aplikacji demonstracyjnej udostępniam zestaw plików fragmentów MP3.

Jakość dźwięku również nie jest doskonała. Mam pewne subtelne usterki. Udało mi się to poprawić, wysyłając większe porcje danych MP3, ale wciąż są drobne trzaski.

EDYCJA: Udało mi się poprawić jakość dźwięku. Wygląda na to, że metoda dekodowania Web Audio nie jest tak naprawdę zaprojektowana do dekodowania ciągłych fragmentów danych MP3.

+0

Ten link jest uszkodzony. – ma11hew28

+1

Zobacz http://stackoverflow.com/a/13315068/612262 odnośnie "ważnych fragmentów mp3". – biril

+8

Czy możesz przesłać swoje rozwiązanie? Próbuję też przesyłać dane MP3 do websocket. – Light

3

W twoim przypadku context.decodeAudioData oczekuje ArrayBuffer danych binarnych, chciałbym zaproponować konwersja klocek na ciąg base64, a następnie do ArrayBuffer stronie klienta dla najbardziej przewidywalne wyniki. This script powinien być dobrym punktem wyjścia do dekodowania po stronie klienta z base64 danych podzielonych na porcje.

Dodawanie linię data = Base64Binary.decodeArrayBuffer(data); tuż po otrzymaniu danych (base-64 zakodowany ciąg) by rade ...

+0

Dziękuję za odpowiedź, ale nie mogę jej uruchomić ze skryptem. Wynikowy ArrayBuffer jest dłuższy niż powinien. W każdym razie chciałbym zrezygnować z Base64 z powodu jego nadmiaru. Myślę, że sam znalazłem rozwiązanie. Zamierzam to wkrótce opublikować. –

+1

@Fair Dinkum Thinkum Chciałbym poznać Twoje rozwiązanie. – fyasar

+0

@fyasar Moim rozwiązaniem było użycie modułu 'ws' zamiast socket.io. W tym czasie socket.io nie był zdolny do obsługi danych binarnych. Nie jestem pewien, czy tak jest nadal. –

Powiązane problemy