web-dev-qa-db-ja.com

NodeJSサーバーからクライアントにライブストリーミングオーディオを取得する

1つのクライアントからサーバー、複数のリスナークライアントへのリアルタイムのライブオーディオストリームが必要です。

現在、クライアントからの録音が機能しており、socket.ioを介してオーディオをサーバーにストリーミングしています。サーバーはこのデータを受信し、このストリームをリッスンするクライアントに(socket.io?を介しても)オーディオをストリーミングする必要があります。できるだけリアルタイムでなければなりません(遅延を最小限に抑えます)。

GetUserMediaを使用してマイクを録音しています(ここでは、ブラウザーの互換性は重要ではありません)。クライアントがHTML5オーディオタグを使用してストリームをリッスンしてほしい。サーバーで受信したデータは、タイプaudio/wavのblobにパックされたチャンク(現在は700でパックされています)です。

これはサーバーに送信するための私のコードです:

mediaRecorder.ondataavailable = function(e) {
    this.chunks.Push(e.data);
    if (this.chunks.length >= 700)
    {
        this.sendData(this.chunks);
        this.chunks = [];
    }
};
mediaRecorder.sendData = function(buffer) {
    blob = new Blob(buffer, { 'type' : 'audio/wav' });
    socket.emit('voice', blob);
}

サーバーでは、次のようにクライアントにチャンクを送信できます。

socket.on('voice', function(blob) {
    socket.broadcast.emit('voice', blob);
});

クライアントでは、次のように再生できます。

var audio = document.createElement('audio');
socket.on('voice', function(arrayBuffer) {
    var blob = new Blob([arrayBuffer], { 'type' : 'audio/wav' });
    audio.src = window.URL.createObjectURL(blob);
    audio.play();
});

これは、私が送信するチャンクの最初のblobに対して機能しますが、新しいURLソースにaudio.srcを変更し続けることは許可されていないため、これは有効なソリューションではありません。

サーバー上で何らかのストリームを作成する必要があると思います。これをリスニングクライアントのHTML5のオーディオタグに挿入できますが、方法がわかりません。チャンクを含む受信したBLOBは、このストリームにリアルタイムで追加する必要があります。

これを行うための最良のアプローチは何ですか?クライアントのマイクからサーバーに直接行っていますか?

13

ここのパーティーには少し遅れますが、まだ完了していない場合は、WebオーディオAPIがあなたの友達になるようです。オーディオエレメントにアタッチすることで、いじりを行うことなく、オーディオストリームを出力デバイスに直接再生できます。

私は同じことをしているのを見ていて、あなたの質問は私の質問に答えました-クライアントからサーバーにデータを取得する方法。 WebオーディオAPIの利点は、ストリームを一緒に追加して、サーバー上のオーディオエフェクトに適用できることです。

MDN WebオーディオAPI

Ioイベントは、オーディオコンテキストのオーディオバッファオブジェクトのデータを置き換える必要があります。オーディオ処理は、各クライアントに単一のストリームとして送信される前に、nodeJS Webオーディオコンテキストで発生する可能性があります。

2
Chris Cook

次のようにaudiosrcを動的に変更できます(mp3タイプを想定):

<audio id="audio" controls="controls">
    <source id="mp3Source" type="audio/mp3"></source>
        Your browser does not support the audio format.
</audio>

ソケットイベントを受信するたびに次の関数を呼び出します。

function updateSource() { 
        var audio = document.getElementById('audio');

        var source = document.getElementById('mp3Source');
        source.src= <blob>;

        audio.load(); //call this to just preload the audio without playing
        audio.play(); //call this to play the song right away
    }
1
Aman Gupta