MediaRecorder recording remote stream using VP9 codec doesn't work

440 Views Asked by At

I tried to use MediaRecorder to record remote video stream using codec VP9, but I can only get a video that cannot play.

Env: latest Chrome (105.0.5195.127).

The stream is so common.

stream = await navigator.mediaDevices.getDisplayMedia({
      video: {
        width: { ideal: 9999 },
        height: { ideal: 9999 }
      },
      audio: false
    });

For auto record, I use setTimeout to stop MediaRecorder. downloadBlob uses <a> to download blob as .webm file, I think this is not where the problem lies.

export function record(stream, duration) {
  const recorder = new MediaRecorder(stream, {
    mimeType: 'video/webm;codecs=vp9'
  });

  const chunks = [];
  recorder.ondataavailable = e => {
    if (e.data.size > 0) {
      chunks.push(e.data);
    }
  };
  recorder.onstop = () => {
    downloadBlob(
      new Blob(chunks, {
        type: chunks[0].type
      }),
      `filename.webm`
    );
  };

  recorder.start();

  setTimeout(() => {
    recorder.stop();
  }, duration);
}

I trigger record(localStream) after pc.addTrack and transceiver.setCodecPreferences (If required, I can also provide these codes), and localStream can be recorded correctly, which means I can play it in PotPlayer and the codec shows VP90.

However, when I trigger record(remoteStream) in pc.ontrack, I cannot play the downloaded video. By the way, the video can correctly show by <video>.

I noticed that when I use console.log(e.data.size) in MediaRecorder.ondataavailable, recording local stream shows 12255987 (a large number) and recording remote stream only shows 3501. I think this is the real problem, but I can't solve it.


By the way, I used to encounter a problem about addIceCandidate. The receiver pc will receive candidate message before set remote desc, so I create a queue at the sender side to make sure both sides set remote&local desc before exchange ICE candidate. I have no idea if this is a stupid operation.

const candidateQueue = [];
this.pc.onicecandidate = e => {
  if (e.candidate) {
    candidateQueue.push(e.candidate);
    if (this.pc.currentRemoteDescription) {
      candidateQueue.forEach(c =>
        this.server.send('candidate', JSON.stringify(c))
      );
      candidateQueue.length = 0;
    }
  }
};

New progress! If I remove transceiver.setCodecPreferences, recorder can record VP9 codec video correctly. However, in my opinion, the VP9 codec just takes place while recording, RTCPeerConnection still use VP8 to transmit video info. Thus I cannot achieve my goal to measure video quality while transmitting by different codecs.

1

There are 1 best solutions below

0
GStarP On

New progress! Problem solved. If you don't pass mimeType to MediaRecorder and don't pass type to Blob, then video can be correctly recorded, and the codec shows VP9. I wonder if someone can tell me why. I will also try to read the source code and share my opnion later.