web-dev-qa-db-ja.com

node.jsとsocket.ioを使用してWebSocketを介してMP3データをストリーミングする方法は?

Node.jsとsocket.ioを使用してWebSocket経由でMP3データをストリーミングする際に問題が発生しました。すべてが機能しているように見えますが、decodeAudioDataは私には公平に機能しません。

これは私のおもちゃのサーバーです:

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

クライアントはデータを文字列型として受け取りますが、データをdecodeAudioDataにフィードしたいのですが、文字列が気に入らないようです。 decodeAudioDataを呼び出すと、次のエラーメッセージが表示されます。

Uncaught Error: SYNTAX_ERR: DOM Exception 12

DecodeAudioDataにはArrayBufferに保存されたデータが必要だと思います。データを変換する方法はありますか?

これはクライアントコードです:

<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>
18
Jan Deinhard

私は自分でWebsocketを介してMP3データをストリーミングする方法を見つけました。

1つの問題は、MP3データのチャンクサイズでした。データをデコードできるようにするには、Web AudioAPIに有効なMP3チャンクを供給する必要があるようです。おそらく驚くことではありません。私のデモアプリでは、MP3チャンクファイルのセットを提供しています。

また、オーディオの品質は完璧ではありません。微妙な不具合があります。 MP3データの大きなチャンクを送信することでそれを改善することができましたが、それでも小さなパチパチ音がします。

編集:私はオーディオ品質を改善することができました。 Web AudioメソッドdecodeAudioDataは、MP3データの連続したチャンクをデコードするように実際には設計されていないようです。

11
Jan Deinhard

あなたの場合、context.decodeAudioDataはバイナリデータのArrayBufferを期待しています。最も予測可能な結果を​​得るために、チャンクをbase64文字列に変換してから、クライアント側のArrayBufferに変換することをお勧めします。 このスクリプト は、チャンク化されたデータのbase64からのクライアント側のデコードの開始点として適しています。

データ(base-64でエンコードされた文字列)を取得した直後にdata = Base64Binary.decodeArrayBuffer(data);で行を追加すると、トリックが実行されます...

3
Tracker1

Socket.ioはまだバイナリ転送をサポートしていないようです。したがって、 websocket.io をここで使用できます。

  1. https://github.com/LearnBoost/socket.io/issues/511#issuecomment-2370129
  2. https://github.com/LearnBoost/socket.io/issues/680#issuecomment-308349
0
Anant Gupta