如何使用Socket.io实时流式传输音频?

4
我目前在使用socket.io创建一个HTML和JS的聊天应用程序。我可以轻松地在两台计算机之间发送书面消息进行通信。我的问题是,我无法弄清如何将一台计算机中实时录制的语音发送到另一台计算机。我正在使用“navigator.getUserMedia”从麦克风记录音频,它工作得很好,但我不能通过Socket.io将其发送到另一台计算机。我知道我可以开始录制,然后停止,最后发送结果,但这不是我需要的,我需要的是实时流式传输。 这是服务器的代码:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var path = require('path');
var users = [];

app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){

socket.on('add user', function(user_id){
    users.push(user_id);
});

socket.on('chat message', function(msg){
    io.emit('chat message', msg);
});
socket.on('voice sent', function(msg){
    io.emit('voice received', msg);
});
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

以下是客户端JavaScript代码:

$(function () {
    var socket = io();
    var user_id = Math.random();

    socket.emit('add user', user_id);

    $('form').submit(function(){
      socket.emit('chat message', {"message": $('#m').val(), "user": user_id});
      $('#m').val('');
      return false;
    });
    socket.on('chat message', function(msg){
      if(msg.user == user_id){
        $('#messages').append($('<li class="mine">').text(msg.message));
      }
      else{
        $('#messages').append($('<li>').text(msg.message));
      }

    });

    socket.on('voice received', function(msg){
      var audio = document.querySelector('audio'); 
      audio.src = window.URL.createObjectURL(stream);
    });

    navigator.getUserMedia = navigator.getUserMedia ||
                     navigator.webkitGetUserMedia ||
                     navigator.mozGetUserMedia;
    if (navigator.getUserMedia) {
       console.log('getUserMedia supported.');
       navigator.getUserMedia ({audio: true}, successCallback, errorCallback);
    } else {
       console.log('getUserMedia not supported on your browser!');
    }

    function successCallback(stream){
       socket.emit('voice sent', stream);
    }

    function errorCallback(error) {
      console.error('An error occurred: [CODE ' + error.code + ']');
    }
  });

我希望有人能帮助我。谢谢。


你可以使用webRTC,看一下文档,它会帮助你的。 - Bhaumik Pandhi
发送或接收音频需要录制和渲染音频的行为...在您的努力中,我会编写代码来处理这些职责,然后再尝试通过网络发送二进制数据...我曾经使用套接字来发送音频,但在我看来,那只是简单的部分...网页具有流媒体音频功能花费了15年的时间,这其中有原因。 - Scott Stensland
非常感谢@PandhiBhaumik,我终于找到了解决办法。它运行得很好。 - Nestoraj
你用了什么? - Bhaumik Pandhi
我使用了Simple-Peer和GetUserMedia:https://www.npmjs.com/package/simple-peer && https://www.npmjs.com/package/getusermedia。项目完成后,我会上传到github并分享链接 ;) - Nestoraj
3个回答

2

我尝试这样做,过了一会儿我就做到了:

最初的回答:

export default {
  data() {
    return {
      audioCtx: new AudioContext(), // for get stream from mic and send via socket
      audioC: new AudioContext(), // for receive data from socket and translate and play 
    }
  },
  created() {
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia

    if (navigator.getUserMedia) {
      console.log('getUserMedia supported.')

      navigator.getUserMedia(
        { audio: true },
        stream => {
          const source = this.audioCtx.createMediaStreamSource(stream)
          const processor = this.audioCtx.createScriptProcessor(2048, 1, 1)

          source.connect(processor)
          processor.connect(this.audioCtx.destination)

          processor.onaudioprocess = e => {
            this.$store.state.mic.Emit('Voice', e.inputBuffer.getChannelData(0))
          }

          this.$store.state.mic.On('Voice', msg => {
            const fbu = new Float32Array(Object.values(JSON.parse(msg)))
            const audioBuffer = this.audioC.createBuffer(1, 2048, this.audioC.sampleRate)

            audioBuffer.getChannelData(0).set(fbu)

            const sourceNode = new AudioBufferSourceNode(this.audioC, { buffer: audioBuffer })

            sourceNode.connect(this.audioC.destination)
            sourceNode.start(0)
          })

          this.audioC.resume()
        },
        err => console.error(err)
      )
    }
  }
}

服务器将除发送方客户端外的所有内容发送给所有客户端,这是最初的回答。但仍存在问题,由于不同的AudioBufferSourceNode,通话质量不佳,声音被分割和切断。


是的,通过改变波特率并降低语音质量,问题得到了解决。 - hamid hassani
onaudioprocess已被弃用!! - Declan Nnadozie

1
在这段代码块中。
    socket.on('voice received', function(msg){
      var audio = document.querySelector('audio'); 
      audio.src = window.URL.createObjectURL(stream);
    });

stream在任何地方都没有定义....我认为这可能会解决你的问题

    socket.on('voice received', function(msg){
      var audio = document.querySelector('audio'); 
      audio.src = window.URL.createObjectURL(msg);
    });

0

1
目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Albert Logic Einstein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接