How can I add predefined length to audio recorded from MediaRecorder in Chrome?

mediarecorder save to file javascript
mediarecorder android
mediarecorder safari
mediarecorder upload to server
mediarecorder wav
mediarecorder mp4
mediarecorder typescript
mediastreamrecorder

I am in the process of replacing RecordRTC with the built in MediaRecorder for recording audio in Chrome. The recorded audio is then played in the program with audio api. I am having trouble getting the audio.duration property to work. It says

If the video (audio) is streamed and has no predefined length, "Inf" (Infinity) is returned.

With RecordRTC, I had to use ffmpeg_asm.js to convert the audio from wav to ogg. My guess is somewhere in the process RecordRTC sets the predefined audio length. Is there any way to set the predefined length using MediaRecorder?

This is a chrome bug.

FF does expose the duration of the recorded media, and if you do set the currentTimeof the recorded media to more than its actual duration, then the property is available in chrome...

var recorder,
  chunks = [],
  ctx = new AudioContext(),
  aud = document.getElementById('aud');

function exportAudio() {
  var blob = new Blob(chunks, {
    type: 'audio/ogg'
  });
  aud.src = URL.createObjectURL(new Blob(chunks));

  aud.onloadedmetadata = function() {
    // it should already be available here
    log.textContent = ' duration: ' + aud.duration;
    // handle chrome's bug
    if (aud.duration === Infinity) {
      // set it to bigger than the actual duration
      aud.currentTime = 1e101;
      aud.ontimeupdate = function() {
        this.ontimeupdate = () => {
          return;
        }
        log.textContent += ' after workaround: ' + aud.duration;
        aud.currentTime = 0;
      }
    }
  }
}

function getData() {
  var request = new XMLHttpRequest();
  request.open('GET', 'https://upload.wikimedia.org/wikipedia/commons/4/4b/011229beowulf_grendel.ogg', true);
  request.responseType = 'arraybuffer';
  request.onload = decodeAudio;
  request.send();
}


function decodeAudio(evt) {
  var audioData = this.response;
  ctx.decodeAudioData(audioData, startRecording);
}

function startRecording(buffer) {

  var source = ctx.createBufferSource();
  source.buffer = buffer;
  var dest = ctx.createMediaStreamDestination();
  source.connect(dest);

  recorder = new MediaRecorder(dest.stream);
  recorder.ondataavailable = saveChunks;
  recorder.onstop = exportAudio;
  source.start(0);
  recorder.start();
  log.innerHTML = 'recording...'
  // record only 5 seconds
  setTimeout(function() {
    recorder.stop();
  }, 5000);
}

function saveChunks(evt) {
  if (evt.data.size > 0) {
    chunks.push(evt.data);
  }

}



getData();
<audio id="aud" controls></audio><span id="log"></span>

How can I add predefined length to audio recorded from , I am in the process of replacing RecordRTC with the built in MediaRecorder for recording audio in Chrome. The recorded audio is then played in the program  How can I add predefined length to audio recorded from MediaRecorder in Chrome? 3. Audio recorded with MediaRecorder on Chrome missing duration. 2.

Thanks to @Kaiido for identifying bug and offering the working fix.

I prepared an npm package called get-blob-duration that you can install to get a nice Promise-wrapped function to do the dirty work.

Usage is as follows:

// Returns Promise<Number>
getBlobDuration(blob).then(function(duration) {
  console.log(duration + ' seconds');
});

Or ECMAScript 6:

// yada yada async
const duration = await getBlobDuration(blob)
console.log(duration + ' seconds')

Record Audio and Video with MediaRecorder | Web, The MediaRecorder API enables you to record audio and video from a web app. It's available now in Firefox and in Chrome for Android and desktop. default. Next, add a data handler and call the start() method to begin recording: be given a timeSlice argument that specifies the length of media to capture for each Blob. How can I add predefined length to audio recorded from MediaRecorder in Chrome? 3. Audio recorded with MediaRecorder on Chrome missing duration. 0.

A bug in Chrome, detected in 2016, but still open today (March 2019), is the root cause behind this behavior. Under certain scenarios audioElement.duration will return Infinity.

Chrome Bug information here and here

The following code provides a workaround to avoid the bug.

Usage : Create your audioElement, and call this function a single time, providing a reference of your audioElement. When the returned promise resolves, the audioElement.duration property should contain the right value. ( It also fixes the same problem with videoElements )

/**
 *  calculateMediaDuration() 
 *  Force media element duration calculation. 
 *  Returns a promise, that resolves when duration is calculated
 **/
function calculateMediaDuration(media){
  return new Promise( (resolve,reject)=>{
    media.onloadedmetadata = function(){
      // set the mediaElement.currentTime  to a high value beyond its real duration
      media.currentTime = Number.MAX_SAFE_INTEGER;
      // listen to time position change
      media.ontimeupdate = function(){
        media.ontimeupdate = function(){};
        // setting player currentTime back to 0 can be buggy too, set it first to .1 sec
        media.currentTime = 0.1;
        media.currentTime = 0;
        // media.duration should now have its correct value, return it...
        resolve(media.duration);
      }
    }
  });
}

// USAGE EXAMPLE :  
calculateMediaDuration( yourAudioElement ).then( ()=>{ 
  console.log( yourAudioElement.duration ) 
});

Audio recorded with MediaRecorder on Chrome missing duration , I have looked at posts like this: How can I add predefined length to audio recorded from MediaRecorder in Chrome? But even trying that, I got errors when trying  It's not as nice as being allowed to drag a note to an arbitrary length, like in LMMS, but it seems to work out ok. Maybe eventually I'll see if I can get it possible to drag a note to a certain length. demos: Intrada - Johann Pezel (1639 - 1694). One of my favorite brass quintet pieces! Sand Canyon (Kirby's Dream Land 3) - Jun Ishikawa

Thanks @colxi for the actual solution, I've added some validation steps (As the solution was working fine but had problems with long audio files).

It took me like 4 hours to get it to work with long audio files turns out validation was the fix

        function fixInfinity(media) {
          return new Promise((resolve, reject) => {
            //Wait for media to load metadata
            media.onloadedmetadata = () => {
              //Changes the current time to update ontimeupdate
              media.currentTime = Number.MAX_SAFE_INTEGER;
              //Check if its infinite NaN or undefined
              if (ifNull(media)) {
                media.ontimeupdate = () => {
                  //If it is not null resolve the promise and send the duration
                  if (!ifNull(media)) {
                    //If it is not null resolve the promise and send the duration
                    resolve(media.duration);
                  }
                  //Check if its infinite NaN or undefined //The second ontime update is a fallback if the first one fails
                  media.ontimeupdate = () => {
                    if (!ifNull(media)) {
                      resolve(media.duration);
                    }
                  };
                };
              } else {
                //If media duration was never infinity return it
                resolve(media.duration);
              }
            };
          });
        }
        //Check if null
        function ifNull(media) {
          if (media.duration === Infinity || media.duration === NaN || media.duration === undefined) {
            return true;
          } else {
            return false;
          }
        }

    //USAGE EXAMPLE
            //Get audio player on html
            const AudioPlayer = document.getElementById('audio');
            const getInfinity = async () => {
              //Await for promise
              await fixInfinity(AudioPlayer).then(val => {
                //Reset audio current time
                AudioPlayer.currentTime = 0;
                //Log duration
                console.log(val)
              })
            }

How can I add predefined length to audio recorded , I am in the process of replacing RecordRTC with the built in MediaRecorder for recording audio in Chrome. The recorded audio is then played in the program  • To use MediaRecorder in Chrome 47 and 48, enable experimental Web Platform features from the chrome://flags page. • Audio recording work in Firefox and in Chrome 49 and above; Chrome 47 and 48 only support video recording. • In Chrome on Android you can save and download recordings made with MediaRecorder, but it's not yet possible to

MediaRecorder, I am in the process of replacing RecordRTC with the built in MediaRecorder for recording audio in Chrome. The recorded audio is then played  Encodes the audio using the Base64 scheme to represent the audio in a string format that can be embedded in an HTTP request. Sends an HTTP request to the microservice. The request includes the encoded audio message along with metadata that provides additional information about the payload. The app uses the Cronet Library to manage the network

Using the MediaStream Recording API, If this attribute is false , MediaRecorder will record silence for audio that duration, rather than the default behavior of recording the media in a  CSS can make element float to one side, mask overflow item, and change writing directions. You can imagine, this layout stage has a mighty task. In Chrome, a whole team of engineers works on the layout. If you want to see details of their work, few talks from BlinkOn Conference are recorded and quite interesting to watch.

Recording Audio in the Browser Using the MediaStream Recorder API, The MediaStream Recording API makes it easy to record audio To demonstrate basic usage of the MediaRecorder API, we have built We wanted to give the first two (the header and the controls) fixed label { font-family: '​NotoColorEmoji'; font-size: 3rem; position: mimeType, Chrome Full support 49. In Chrome 76 you can hide the Add to Home screen mini-infobar Augmented reality with model-viewer Paint Holding - reducing the flash of white on same-origin navigations

Comments
  • I'm having the exact same problem. Did you find a solution?
  • What do you mean predefined length? Can you just have a timer that is started when the recording starts and then stop it at the appropiate time?
  • @Tom Chen when I inspect my recorded audio files after a recording (using command-line '$ ffmpeg -i test.webm' I see definition is set as N/A. Did you find a way to set the length?
  • There is a bug: crbug.com/642012. I suggest we "star" it so the developers can prioritize accordingly.
  • @miguelao, yep I filed this one which has been merged to the one you mentioned.
  • The chrome bug mentioned here has been marked as WontFix by the chromium team, so it looks looks like we need to rely on a library like ts-ebml if we want to edit the actual file.