Search code examples
google-chromewebrtcrecordrtcweb-mediarecordermediarecorder-api

Why does MediaRecorder fail to start? (error: there's no audio or video tracks available) RecordRTC


UPDATE: Current best hypothesis is that this is somehow caused by the large school/university networks— other users aren't having the problem.


I'm using RecordRTC to record audio. That relies on MediaRecorder.

Upon first starting the recording, this (caught) error is logged:

DOM exception: failed to execute start on Media recorder: The 
MediaRecorder failed to start because there are no audio or video 
tracks available

Before that, RecordRTC calls the MediaRecorder API:

Using recorderType:MediaStreamRecorder
Passing following config over MediaRecorder API.Object {audio: "true", mimeType: "audio/webm", checkForInactiveTracks: "true", type: "audio", initCallback: "[object Function]"}

And here's the traceback in the code. It starts with a call to startRecording (in a redux saga):

const recorder = yield select(getRecorder)
yield call(recorder.startRecording)

Here's startRecording

startRecording = () => {

try {
  this.captureUserMedia((stream) => {
    try {
       this.rtcRecorder.startRecording()
     this.recording = true
    } catch (err) {
      sendEmail(err, "inner startRecording failed", "[email protected]")
      console.log("inner startRecording ERROR: ", err)
    }
  });
} catch (err) {
    sendEmail(err, "startRecording failed", "[email protected]")
    console.log("startRecording ERROR: ", err)
}

}

Here's captureUserMedia:

captureUserMedia(callback) {
 var params = { audio: true, video: false };

 navigator.getUserMedia(params, callback, (error) => {
   // alert(JSON.stringify(error));
   console.log('USER MEDIA ERROR::   ' + JSON.stringify(error))
   callback(null, error)
 });
};

The error seems to occur at this line in particular of startRecording:

this.rtcRecorder.startRecording()

There are a few more details that might be helpful in solving this:

  1. Chrome version does not seem to be the problem: some users with v61.0.3163.100 have the problem, while others don't
    1. For the users who experience the problem, it seems to occur every time.
    2. Apparently, navigator.getUserMedia is deprecated, but it still should function— the complicated logic of the promise could be introducing a bug.

UPDATE:

  1. The problem has happened to two users who were on large networks (A university network and a public school district network). It has not yet happened to any users who were on private home networks....

Let me know what other info would be helpful and I'll respond immediately. Thank you.

UPDATE:

Muaz Khan suggested adding a hidden audio element to prevent the stream and tracks from being stopped/released. Here's the additional code that was added before capturing a stream (when the recorder is first initialized):

var hiddenAudio = document.createElement('audio');
hiddenAudio.srcObject = stream // this line is required to make sure stream tracks aren't stopped/released
hiddenAudio.muted = true
hiddenAudio.play()

UPDATE 2:

But it's still not working. A thought on why that may not have worked:

  1. I'm not sure that the hiddenAudio HTML element is actually persisting and capturing the stream. (It could be scoped incorrectly.)

I'm left wondering if there's a subtle error in the callback hell of navigator.getUserMedia and that using the newer navigator.mediaDevices getusermedia (which relies on promises) would be simpler to follow.

The other possibility is that the error is introduced when the recorder is initialized— that's here:

initialize = (callback) => {

if (!!this.rtcRecorder) {
  console.log('Attempted to initialize an already initialized recorder but that\'s expected')
  return
}

console.log('initialize Recorder -- requestUserMedia')
this.captureUserMedia((stream, error) => {

  if (error) {
    console.log('!!errror capturing user media!!')
    return callback && callback(error)
  }

  // TODO: detect if system can play webms

  // <-- smaller filesize
  // this.rtcRecorder = RecordRTC(stream, { recorderType: RecordRTC.StereoAudioRecorder, bitsPerSecond: 30000, numberOfAudioChannels: 1, mimeType: 'audio/wav' });

  try {

    // the MUAZ KHAN edits
    var hiddenAudio = document.createElement('audio');
    hiddenAudio.srcObject = stream // this line is required to make sure stream tracks aren't stopped/released
    hiddenAudio.muted = true
    hiddenAudio.play()


    this.rtcRecorder = RecordRTC(stream,  { audio: 'true', mimeType: 'audio/webm', checkForInactiveTracks: 'true' });
    callback && callback(null)
    return true
  } catch (err) {
    sendEmail(err, "captureMedia (inner-most) startRecording failed", "[email protected]")
    console.log("captureMedia (inner-most) startRecording ERROR: ", err)
    callback && callback(null)
    return true
  }


});
};

Thanks again.

UPDATE:

Including here the profiles of two users who are having this problem (both of large public school/university networks). The problem is not happening to users on private home networks:

enter image description here enter image description here


Solution

  • The problem was in captureUserMedia which needed access to the stream:

    captureUserMedia(callback) {
      var params = { audio: true, video: false };
      navigator.getUserMedia(params, (stream) => {
        callback(stream)
      }, (err) =>  {
        callback(null, err)
      })
      return
    }