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

2

5

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?

Jacksmelt answered 4/9, 2019 at 10:0 Comment(0)
J
4

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);
Jacksmelt answered 5/9, 2019 at 7:35 Comment(3)
I am getting Index:269 Uncaught ReferenceError: callInfo is not defined error on !callInfo.isCallActive. May you please suggest a quick fix? I have already searched the issue online with no success.Fagin
@Muaz Khan I need your help as well. I've used the approach you've presented and I am getting only the first chunk of recorded video saved and the remaining chunks (after a set interval) is not correctly saved. Most probably the issue is the same one meta data problemFagin
when you stop and restart again, will it have break in video like milliseconds ?Velma
D
3

(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.

Distended answered 4/9, 2019 at 23:31 Comment(1)
This is useful, but I've solved with another method. You can check my answer below.Jacksmelt

© 2022 - 2024 — McMap. All rights reserved.