потоковое аудио с микрофона через веб-сокет. Я вижу отправляемые данные, но не слышу их на принимающей стороне клиента

Я пытаюсь транслировать захваченный звук микрофона через веб-сокет. Я вижу, что буферный массив отправляется, и в массиве есть действительные данные, но принимающая сторона клиента не может их слышать. Я почти уверен, что моя функция воспроизведения правильная, потому что я могу генерировать белый шум, заполняя массив случайными числами и используя функцию воспроизведения, чтобы услышать его. Я думаю, может быть, звук, который он транслирует, слишком тихий, чтобы его можно было услышать, потому что числа, сгенерированные в массиве, в основном находятся в диапазоне .000###. Есть идеи? Захват звука с микрофона и его трансляция кажутся слишком сложными... :/

 //broadcasting side 
  navigator.mediaDevices.getUserMedia({audio: true,video: false}) // request cam
        .then(stream => {
         vid.srcObject = stream;
         context = new AudioContext();
         var source = context.createMediaStreamSource(stream);
         var processor = context.createScriptProcessor(1024, 2, 2);
         source.connect(processor);
         processor.connect(context.destination);

         processor.onaudioprocess = function(e) {
           audiodata = e.inputBuffer.getChannelData(1);
          socket.send(JSON.stringify({sound: audiodata, to: to, from: '$username', text:''}));
         };
         return vid.play(); // returns a Promise
       });



//receiving side object to array 

       if(typeof (message.sound) != "undefined"){
         //$('#video_stream_btn').trigger('click');
          var json_sound = message.sound;
          var array_sound = [];
          for(var i in json_sound){
            array_sound.push([i, json_sound [i]]);
          }
         if(typeof(context) == 'undefined'){
           context = new AudioContext();
         }
         play_sound(array_sound, context);
         return;
       }


// receiving side play sound function 

    function play_sound(raw,context){

        //alert(raw.length);
        var audioBuffer = context.createBuffer(1, raw.length, context.sampleRate);
        audioBuffer.getChannelData(0).set(raw);
        var source = context.createBufferSource();
        source.buffer = audioBuffer;
        source.connect(context.destination);
        source.start(0);

    }

person Noob01    schedule 06.07.2019    source источник


Ответы (1)


Для тех, кто пытается понять это. В итоге я закодировал его в массив int16, а затем отправил через сокет, где клиент закодировал его обратно в массив float32 и передал функции play_sound. По сути, я просто украл кучу вещей из stackoverflow и подделывал их, пока не сделал, потому что я не такой умный :)

захват микрофона и преобразование в массив int16, а затем отправка его через сокет

 navigator.mediaDevices.getUserMedia({audio: {sampleSize: 16, channelCount: 2},video: true}) // request cam
        .then(stream => {
         vid.srcObject = stream; // don't use createObjectURL(MediaStream)
         context = new AudioContext();
         var source = context.createMediaStreamSource(stream);
         var processor = context.createScriptProcessor(1024, 2, 2);
         source.connect(processor);
         processor.connect(context.destination);

         processor.onaudioprocess = function(e) {
          // Do something with the data, i.e Convert this to WAV
          audiodata = new Int16Array(convertFloat32ToInt16(e.inputBuffer.getChannelData(0)));
          console.log(audiodata);
          socket.send(JSON.stringify({sound: audiodata, to: to, from: '$username', text:''}));

         };
         return vid.play(); // returns a Promise
       });

соответствующая функция для преобразования захваченного микрофона в массив int16:

function convertFloat32ToInt16(buffer){
          l = buffer.length;
          buf = new Int16Array(l);

      while (l--)
      {
         buf[l] = Math.min(1, buffer[l])*0x7FFF;
      }

      return buf.buffer;

  }

получение json-объекта на стороне клиента в int16array, затем int16array обратно в float32array:

if(typeof (message.sound) != "undefined"){
         //$('#video_stream_btn').trigger('click');
          //var json_sound = message.sound;


         if(typeof(context) == 'undefined'){
           context = new AudioContext();
         }
         sound_array = [];
         for (i in message.sound)
         {
            sound_array[i] = (message.sound [i]);
         }

        //sound_array16 = new Int16Array(sound_array);
        sound_array32 = int16ToFloat32(sound_array);
         play_sound(sound_array32, context);
         return;
       }

соответствующая функция принимающей стороны int16array to float32array:


    function int16ToFloat32(inputArray) {

        let int16arr = new Int16Array(inputArray)
        var output = new Float32Array(int16arr.length);
        for (var i = 0; i < int16arr.length; i++) {
            var int = int16arr[i];
            var float = (int >= 0x8000) ? -(0x10000 - int) / 0x8000 : int / 0x7FFF;
            output[i] = float;
        }
        return output;
    }
person Noob01    schedule 08.07.2019
comment
Uncaught SyntaxError: недопустимый оператор возврата - person Vitalicus; 24.10.2020