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