The following code works when the video observing client is loaded first then the webcam client is loaded second it works flawlessly, however, if the order is switched or in any way the stream is interrupted for example by refreshing either client the stream will fail and the Media Source will change its ready state to closed.
My assumption is that the video being received on start needs initialization headers for starting and since the stream is being read midstream it never gets said initialization headers. I am unsure of how to even add such header to the webm file.
I have tried to change the sequence mode on the source buffer which did nothing. I have tried restarting the video recorder and that works, but my final plan is to have multiple observing clients and the video recorder restarting on every reconnection is not optimal.
Camera Client
main();
function main() {
if (hasGetUserMedia()) {
const constraints = {
video: {
facingMode: 'environment',
frameRate: {
ideal: 10,
max: 15
}
},
audio: true
};
navigator.mediaDevices.getUserMedia(constraints).
then(stream => {
setupRecorder(stream);
});
}
}
function setupRecorder(stream) {
let mediaRecorder = new MediaRecorder(stream, {
mimeType: 'video/webm; codecs="opus, vp9"'
});
mediaRecorder.ondataavailable = e => {
var blob = e.data;
socket.emit('video', blob);
}
mediaRecorder.start(500);
}
The server just broadcasts whatever is received
Observing Client
var sourceBuffer;
var queue = [];
var mediaSource = new MediaSource();
mediaSource.addEventListener('sourceopen', sourceOpen, false);
main();
socket.on('stream', data => {
if (mediaSource.readyState == "open") {
if (sourceBuffer.updating || queue.length > 0) {
queue.push(data.video);
} else {
sourceBuffer.appendBuffer(data.video);
}
}
});
function main() {
videoElement = document.querySelector('#video');
videoElement.src = URL.createObjectURL(mediaSource);
}
function sourceOpen(e) {
console.log('open');
sourceBuffer = mediaSource.addSourceBuffer('video/webm; codecs="opus, vp9"');
sourceBuffer.addEventListener('updateend', () => {
console.log(sourceBuffer.updating, mediaSource.readyState);
if (queue.length > 0 && !sourceBuffer.updating) {
sourceBuffer.appendBuffer(queue.shift());
}
});
}
So the code, in fact, works just in a way that is not correct so nothing is wrong with the server of socket sending. It either has something to do with the MediaRecorder or MediaSource.