When the video observing client is loaded before the webcam client, everything runs smoothly. However, if the order is reversed or there is any interruption in the stream (such as refreshing either client), the Media Source will close and the stream will fail.
It seems that the video initially needs initialization headers to start properly, and when the stream is interrupted midstream, these headers are not received. I am unsure of how to add such headers to the webm file.
I attempted to change the sequence mode on the source buffer without success. Restarting the video recorder did work, but having multiple observing clients with the recorder restarting upon reconnection is not ideal.
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 simply broadcasts whatever it receives.
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 does work in a functioning manner, although not correctly. The issue likely lies with either the MediaRecorder or MediaSource rather than the server or socket sending.