Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MediaRecorder ondataavailable work successfully once

MediaRecorder ondataavailable work successful once. I need to get blob, get it base64, send to my server, decode this base64 to audio blob. This is very strange.

For example, output:

blob1 blob2 blob3 blob4 blob5 blob6 blob7 blob8 blob9

....

I can hear just blob1, other blobs is "disabled".

Try it! This code record audio:

window.startRecord = function(cb){
  var int;
  navigator.mediaDevices.getUserMedia({ audio: true , video:false}).then(function(stream){
    var options = {
      audioBitsPerSecond : 128000,
      videoBitsPerSecond : 2500000,
      mimeType : 'audio/webm\;codecs=opus'
    }

    if(!MediaRecorder.isTypeSupported(options['mimeType'])) options['mimeType'] =  "audio/ogg; codecs=opus";


    window.voice = new MediaRecorder(stream, options);

    voice.start(500);
    voice.ondataavailable = function(data){


      var reader = new FileReader();
      var blob = data.data;

      reader.readAsDataURL(blob);
      reader.onloadend = function () {
        var result = reader.result;

        cb(result);
      }
    };

    voice.onstop = function(){
      console.log('stop audio call');
    }
  });
}

window.convertDataURIToBinary = function(dataURI) {
  var BASE64_MARKER = ';base64,';
  var base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
  var base64 = dataURI.substring(base64Index);
  var raw = window.atob(base64);
  var rawLength = raw.length;
  var array = new Uint8Array(new ArrayBuffer(rawLength));

  for(i = 0; i < rawLength; i++) {
    array[i] = raw.charCodeAt(i);
  }
  return array;
}
<body>
<button onclick="startRecord(function(r){
 
    var binary= convertDataURIToBinary(r);
  var blob=new window.Blob([binary], {type : 'audio/webm'});
  var blobUrl = window.URL.createObjectURL(blob);
  console.log('URL : ' + blobUrl);

  document.getElementById('data').append(blobUrl + `

 | 

    `);
   })">Exec</button>

   <div id="data">
     
   </div>
<body>

</body>
like image 578
DuckerMan Avatar asked Dec 01 '17 14:12

DuckerMan


Video Answer


1 Answers

I am not sure what is the problem you try to highlight, but:

The dataavailable event's data property contains only a chunk of the whole data that has been recorded.
For instance, only the first chunk will contain the metadata needed for the final recorded media.

It is then expected that you will merge all these chunks together at the time you will export them.

And this should be done only once, at the MediaRecorder.stop event.

const chunks = []; // store all the chunks in an array
recorder.ondataavailable = e => chunks.push(e.data);
// merge the chunks in a single Blob here
recoder.onstop = e => export_media(new Blob(chunks));
like image 73
Kaiido Avatar answered Oct 30 '22 14:10

Kaiido