Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecordRTC: Ondataavailable called twice. Only first file is proper, others are corrupted or too small [duplicate]

I want to record local and remote stream at the interval of 2 seconds and upload it to the server with Ajax. But the problem is, the method ondataavailable is called twice so the same video is uploaded to the server twice. The first video is playable and proper, while the rest of the videos are either corrupted or very small (less than one second). The size of all the videos is almost the same!

I've tried with MediaRecorder API also but the problem is the same. I've tried with 5 seconds of the interval but still no luck!

This is how I get the local stream:

navigator.mediaDevices.getUserMedia({
    video: false,
    audio: true
}).then(function (myStream) {
    localStream = myStream;

    localStream.getTracks().forEach(function (track) {
        yourConn.addTrack(track, localStream);
    });
}).catch(function (error) {
    streamAdded = false;
    console.warn('Could not detect microphone');
    return false;
});

This is how I perform recording:

yourConn.ontrack = function (e) {
   remoteVideo.srcObject = e.streams[0];

   let recorder = RecordRTC([localStream, e.streams[0]], {
      mimeType: 'video/webm;codecs=h264',
      type: 'video',
      timeSlice: 5000,
      ondataavailable: function(blob) {
        uploadBlob(blob);
      },
   });

   recorder.startRecording();
}

uploadBlob function:

var formData = new FormData();
formData.append('recorded_file', mp4File);

$.ajax({
    url: myURL,
    data: formData,
    cache: false,
    contentType: false,
    processData: false,
    type: 'POST',
    success: function (response) {
        console.log(response);
    }
});

How can I record both the streams without any issues?

like image 227
ishan shah Avatar asked Sep 04 '19 10:09

ishan shah


2 Answers

(This answer covers MediaRecorder, though I suspect it also applies to the RecordRTC JS library.)

The timeSlice: 5000 argument slices the recording into chunks, calling dataavailable every 5 seconds. But these chunks aren't independently playable. You're expected to join them like this to create a valid media container file:

const data = [];
recorder.ondataavailable = e => data.push(e.data);
recorder.onstop = () => uploadBlob(new Blob(data, {type: data[0].type}));

If uploading everything at the end isn't practical, you can instead try to join the blobs on the server.

like image 170
jib Avatar answered Oct 27 '22 22:10

jib


I've solved this issue by Stop and Restart method. I'm stoping the recorder when I get the first blob, then I upload it and start the recorder again. So that every time I get a complete video.

function initRecorder(remoteStream) {
    recorder = RecordRTC([stream, remoteStream], {
       type: 'video',
    });

    recorder.startRecording();
}

// in ontrack method:

initRecorder(remoteStream);  // initially start recording

let recordingInterval = setInterval(function () {
    if (!callInfo.isCallActive) clearInterval(recordingInterval);

    recorder.stopRecording(function () {
        let blob = recorder.getBlob();
        if(callInfo.isCallActive) {
            initRecorder(remoteStream);  // restart recording
        }
        if (blob.size) { // prevent empty blobs
            uploadBlob(blob, roomId);
        }
    });
}, 5000);
like image 29
ishan shah Avatar answered Oct 27 '22 22:10

ishan shah