RecordRTC:Ondataavailable 调用了两次。只有第一个文件是正确的,其他文件已损坏或太小

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

我想以2秒的间隔录制本地和远程流并使用Ajax将其上传到服务器。但问题是,ondataavailable 方法被调用了两次,所以同一个视频被两次上传到服务器。第一个视频可以正常播放,而其余视频要么损坏要么非常小(不到一秒)。所有视频的大小几乎一样!

我也尝试过使用 MediaRecorder API,但问题是一样的。我试过 5 秒的间隔,但还是不行!

这是我获取本地流的方式:

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;
});

我是这样录音的:

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 函数:

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);
    }
});

如何才能毫无问题地录制两个流?

(此答案涵盖 MediaRecorder,但我怀疑它也适用于 RecordRTC JS 库。)

timeSlice: 5000 参数将录音分成 ,每 5 秒调用一次 dataavailable。但是这些块不能独立播放。您需要加入他们 like this 以创建有效的媒体容器文件:

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

如果最后上传所有内容不切实际,您可以改为尝试加入服务器上的 blob。

我已经通过停止并重新启动方法解决了这个问题。当我得到第一个 blob 时我会停止记录器,然后我上传它并再次启动记录器。以至于我每次都得到一个完整的视频。

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);