MediaStreamRecorder doesn't fire the ondataavailable event
Asked Answered
Y

2

7

I am using an open source JavaScript library MediaStreamRecorder to record audio and video webRTC calls in Mozilla Firefox and Google Chrome.

The calls are recording successfully but I am facing the following issue.

If I use the time interval of 1 second (1000ms) in multiStreamRecorder.start() then multiStreamRecorder.ondataavailable event doesn't fire. And that's why No error or No log in console.

But, if I use the time interval of 1.5 seconds (1500ms) or greater, it fires the multiStreamRecorder.ondataavailable event and everything works perfectly fine. (Only in Video Case)

I want to keep the interval to 1 second (1000ms) only.

var ws;

function start() {

    ws = new WebSocket("wss://xyz/");

    ws.onopen = function () {
        console.log("WebSocket has been opened!");
    };

    ws.onmessage = function (message) {
        console.log("A messsage is received from WebSocket Server.", message);
    };

    ws.onclose = function (e) {
        console.log('WebSocket is closed. Reconnection will be attempted in 5 second.', e.reason);
        setTimeout(function () {
            start();
        }, 5000);
    };

    ws.onerror = function (err) {
        console.error('WebSocket encountered an error: ', err.message, 'Closing WebSocket');
        ws.close();
    };

}

start();


function startRecording(localStream, remoteStream) {

    if (localStream != null && remoteStream != null) {

        multiStreamRecorder = new MultiStreamRecorder([localStream, remoteStream], "video/webm");
        multiStreamRecorder.mimeType = "video/webm";

        multiStreamRecorder.ondataavailable = function (blob) {

            console.log("sending blob to websocket server", blob);
            ws.send(blob);

        };

        // It doesn't work with the 1000ms time interval
        multiStreamRecorder.start(1500);

    }
    else{
        console.error("One or more streams are null.");
    }

}
Yajairayajurveda answered 17/4, 2017 at 13:41 Comment(0)
J
6

I suspect one second is not enough time for the camera stream to warm up. While you can attach a recorder to a stream instantly, it doesn't appear to be ready for play/recording in zero time.

Video elements have .onloadedmetadata to let you wait for data to be ready; recorders do not.

You can make one though (use https fiddle for Chrome):

var haveLoadedMetadata = stream => {
  let preview = document.createElement("video");
  preview.srcObject = stream;
  return new Promise(resolve => preview.onloadedmetadata = resolve); 
};

var start = ms => navigator.mediaDevices.getUserMedia({video: true})
  .then(stream => haveLoadedMetadata(stream)
    .then(() => record(stream, ms))
    .then(recording => {
      stop(stream);
      video.src = link.href = URL.createObjectURL(new Blob(recording));
      link.download = "recording.webm";
      link.innerHTML = "Download recording";
      log("Playing "+ recording[0].type +" recording:");
    }))
  .catch(log);

var record = (stream, ms) => {
  var rec = new MediaRecorder(stream), data = [];
  rec.ondataavailable = e => data.push(e.data);
  rec.start();
  log(rec.state + " for "+ (ms / 1000) +" seconds...");
  var stopped = new Promise((y, n) => (rec.onstop = y, rec.onerror = e => n(e.error || e.name)));
  return Promise.all([stopped, wait(ms).then(() => rec.stop())])
    .then(() => data);
};

var stop = stream => stream.getTracks().forEach(track => track.stop());
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var log = msg => div.innerHTML += "<br>" + msg;
<button onclick="start(1000)">Record 1 second!</button>
<div id="div"></div><br>
<video id="video" height="120" width="160" autoplay></video>
<a id="link"></a>

(Both Chrome and Firefox implement MediaRecorder directly, so I've answered using that).

Jenaejenda answered 17/4, 2017 at 16:15 Comment(3)
MediaRecorder.ondataavailable not firing after windows is minimized or browser tab is switched... Is there any way to prevent it ? or if it is in the nature of the library then how can I resume the process once I switched the tabs and comeback to it again?Yajairayajurveda
I don't know about the library. I use the native one in my fiddle and it does not seem fazed by tab-switching or minimize. E.g. modify it to record 10 seconds. WFM.Jenaejenda
why live video is not coming in this example ?Rape
H
3

I had a similar problem. it didnt fired ondataavailable event unless i started recording and stopped several times. After 2 days found out that problem was my microphone drivers :). It probably keeps trying microphone so it takes few seconds till it figure out that it doesnt work. Once set audio to false all works perfectly. Just no sound lol.

Howl answered 15/5, 2019 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.