提高套接字 io 将音频数据从客户端发送到服务器返回客户端的音质

Joh*_*son 4 javascript audio node.js socket.io getusermedia

这段代码确实有效。每 300 毫秒就会将一块音频数据发送到服务器并返回到套接字空间中的客户端进行播放。只有一个问题。音频质量极差。每 300 秒的间隔就会有一阵短暂的静电噪音,但几乎立即消失。我相信这是因为音频块发送到服务器和返回到房间中的套接字之间的时间间隔。我没有使用像socket io p2p或peerjs这样的webRTC,因为它们真的很复杂,而且我是初学者,所以在这段代码中我可以做些什么来更流畅地播放音频吗?我尝试过不同的操作,例如将 setInterval 函数中的毫秒数更改为 60 并提高到 5000。间隔越低,播放越不稳定,但播放速度越快,但越高,质量越好,但有 5 秒的延迟。

客户:

var constraints = { audio: true };
    navigator.mediaDevices.getUserMedia(constraints).then(function(mediaStream) {
        var mediaRecorder = new MediaRecorder(mediaStream);
        mediaRecorder.onstart = function(e) {
            this.chunks = [];
        };

        mediaRecorder.ondataavailable = function(e) {
            this.chunks.push(e.data);
        };
        mediaRecorder.onstop = function(e) {
            var blob = new Blob(this.chunks);
            var url = <%- JSON.stringify(url) %>;
            socket.emit('radio', {blob : blob, url : url});
        };

        mediaRecorder.start();

        setInterval(function() {
            mediaRecorder.stop()
            mediaRecorder.start();
        }, 300);
    });

    socket.on('voice', function(arrayBuffer) {
        var blob = new Blob([arrayBuffer], { 'type' : 'audio/webm;codecs=opus' });
        var audio = document.createElement('audio');
        audio.src = window.URL.createObjectURL(blob);
        audio.play();
    });
Run Code Online (Sandbox Code Playgroud)

服务器:

socket.on('radio', function(data) {
    socket.broadcast.to(data.url).emit('voice', data.blob);
    socket.join(data.url);
});
Run Code Online (Sandbox Code Playgroud)

O. *_*nes 5

你的音频质量很好。您的问题是音频块之间的播放间隙。好的音频看起来像这样。每个音频样本都是一个 *. 您可能每秒有 44K 个样本或类似的数据。

 ***********************************************
Run Code Online (Sandbox Code Playgroud)

您提供给音频元素的样本如下所示

 ******* ******* ******* *******   ******** *******   ****
Run Code Online (Sandbox Code Playgroud)

注意间隙。这些是流行音乐。请注意,播放音频所需的时间比捕获所需的时间要长。那是因为有间隙。

如果您决定接受它,您的任务是弄清楚如何将音频块放入队列中,以便您的音频播放器可以连续播放它们,并在上一个音频停止时准确地开始下一个音频块。你需要某种“一劳永逸”的机制。

对于 Stack Overflow 问题来说,完全解释这一点需要很多时间,因此我将提供一些提示。

  1. 不要启动和停止您的 mediaRecorder。让它运行。
  2. 在 中输入少量毫秒mediaRecorder.start(nn),例如 10
  3. ondataavailable将您的 blob(样本缓冲区)从事件处理程序(而不是处理程序)通过套接字发送到服务器onstop。这使得它们基本上流式传输到服务器。
  4. 使用 Web Audio API 将示例缓冲区排队到用户的音频设备。大话题。查一下。