I have a forum post form that allows the poster to attach an audio recording and/or a webcam snapshot. Both of these are implemented using the navigator.getUserMedia() API. For the audio I built off a variant of Matt Diamond's well-known recorder.js library, and for the camera capture I adapted some script offered up by David Walsh, available here.
Each function on its own works beautifully. The problem is when a poster tries to make a voice recording and then take a picture, the <video> element doesn't load the camera stream. The browser asks for permission, the webcam light even lights up, but nothing appears on the screen. If I 'restart' the video stream (with a 'take another picture' button that restarts all the relevant elements), it works again, even though it uses the exact same code as the button that starts the camera in the first place.
In the opposite order, first camera, then microphone, everything works fine.
A little code for clarity's sake:
The getUserMedia and AudioContext objects are obtained in the audio recording script thus:
try {
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL;
if (navigator.getUserMedia === !1) {
alert('Your browser doesn\'t support audio recording');
}
function record (o, i) {
if (e.voice.initCalled === !1) {
this.init();
e.voice.initCalled = !0;
}
;
navigator.getUserMedia({audio: true}, function (t) {
var r = e.voice.context.createMediaStreamSource(t);
if (o === !0) {
r.connect(e.voice.context.destination);
}
;
e.voice.recorder = new Recorder(r, {workerPath: e.voice.workerPath});
e.voice.stream = t;
e.voice.recorder.record();
i(t);
}, function () {
alert('No live audio input');
});
}
And in the photo capture script, like this:
function startMediaStream() {
// Put video listeners into place
if (navigator.getUserMedia) { // Standard
navigator.getUserMedia(videoObj, function (stream) {
mediaStream = stream;
video.src = stream;
video.play();
}, errBack);
} else if (navigator.webkitGetUserMedia) { // WebKit-prefixed
navigator.webkitGetUserMedia(videoObj, function (stream) {
mediaStream = stream;
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
else if (navigator.mozGetUserMedia) { // Firefox-prefixed
navigator.mozGetUserMedia(videoObj, function (stream) {
mediaStream = stream;
video.src = window.URL.createObjectURL(stream);
video.play();
}, errBack);
}
}
The question is, what in the script would cause the stream in the second script to fail or somehow be blocked?
Update
Before posting, I decided to be a mensch and try debugging first. What I discovered is some sort of listener (I'm not quite the JavaScript ninja I wish I was, so some of these more advanced concepts are not totally clear to me -- my native tongue is Java) in the recorder.js script that causes the code to loop endlessly on this line (the first one) as soon as the camera turns on :
this.node.onaudioprocess = function(e){
if (!recording) return;
var buffer = [];
for (var channel = 0; channel < numChannels; channel++){
buffer.push(e.inputBuffer.getChannelData(channel));
}
worker.postMessage({
command: 'record',
buffer: buffer
});
};
Sorry for the lengthy post. Any ideas on what to modify in the recorder.js file in order to not have this problem?