2012-01-06 19 views
17

Tengo problemas para transmitir datos de MP3 a través de WebSocket con node.js y socket.io. Todo parece funcionar, pero DecodeAudioData no juega limpio conmigo.Cómo transmitir datos MP3 a través de WebSockets con node.js y socket.io?

Este es mi servidor de juguete:

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/'); 

El cliente recibe los datos como tipo cadena, pero quiero alimentar a los datos a decodeAudioData y parece que no le gusta cuerdas. La llamada a decodeAudioData da como resultado el siguiente mensaje de error:

Uncaught Error: SYNTAX_ERR: DOM Exception 12 

creo decodeAudioData necesita los datos almacenados en un ArrayBuffer. ¿Hay alguna forma de convertir los datos?

Este es el código de cliente:

<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

¿ha encontrado una solución a este problema? – codeAnand

+0

No he encontrado una solución usando socket.io. Ver mi propia respuesta para una solución sin socket.io. –

+0

Socket.io 1.0 tiene soporte para binario, lo intento pero no funciona. También lo intento con websocket, pero exactamente con el mismo error. ¿Tienes un ejemplo de cómo resolver esto ?. – cmarrero01

Respuesta

10

he encontrado una manera de transmitir datos MP3 a través de WebSockets mí mismo.

Un problema fue el tamaño del fragmento de los datos MP3. Parece que la API de Web Audio necesita alimentarse con fragmentos de MP3 válidos para poder decodificar los datos. Probablemente no sea sorprendente. En mi aplicación de demostración, proporciono un conjunto de archivos de fragmentos de MP3.

También la calidad del audio no es perfecta. Tengo algunas fallas técnicas sutiles. Pude mejorar eso enviando grandes cantidades de datos MP3, pero todavía hay pequeños crepitantes.

EDIT: Logré mejorar la calidad del audio. Parece que el método Web Audio decodeAudioData no está diseñado para decodificar fragmentos continuos de datos MP3.

+0

Ese enlace está roto. – ma11hew28

+1

Ver http://stackoverflow.com/a/13315068/612262 con respecto a 'trozos de mp3 válidos'. – biril

+8

¿Puede publicar su solución? También estoy tratando de transmitir datos MP3 a websocket. – Light

3

En su caso context.decodeAudioData espera un ArrayBuffer de los datos binarios, sugeriría la conversión de su trozo de una cadena base64, a continuación, a un lado del cliente para ArrayBuffer los resultados más predecibles This script debe ser un buen punto de partida para la decodificación del lado del cliente desde base64 de los datos fragmentados.

Adición de una línea con data = Base64Binary.decodeArrayBuffer(data); justo después de conseguir sus datos (base 64 cadena codificada) haría el truco ...

+0

Gracias por su respuesta, pero no puedo hacer que funcione con el script. El ArrayBuffer resultante es más largo de lo que debería ser. Me gustaría evitar Base64 de todos modos porque está sobrecargado. Creo que he encontrado una solución yo mismo. Voy a publicarlo aquí pronto. –

+1

@Fair Dinkum Thinkum Me gustaría saber su solución. – fyasar

+0

@fyasar Mi solución fue utilizar el módulo 'ws' en lugar de socket.io. En ese momento, socket.io no era capaz de manejar datos binarios. No estoy seguro si ese sigue siendo el caso. –

Cuestiones relacionadas