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