Reputation: 3
I created a web (Vue.js) and desktop app (Tauri) that records my camera's video stream with getUserMedia. The camera is 4K resolution which is recognized as a webcam by CamLink. And finally for the recording part I use MediaRecorder. It would have been so beautiful if it were that simple...
Picture quality is really good but I quickly discovered that it didn't record at a consistent framerate. The videos are sometimes 29.042 fps, then 30.512 fps, etc. This makes a big problem for what I want to do later. When I open the videos in after effects it jerks.
I implemented @kaiido solution with the help of the canvas but I wanted to know if there was a solution to do it without the canvas like use only MediaRecorder since it degrades the performance of the app.
I don't want to manipulate the video. I want to have the best possible quality in a constant frame rate.
Upvotes: 0
Views: 1303
Reputation: 108651
For what it's worth, getUserMedia and MediaRecorder don't generate broadcast-quality video streams. Dropped and jittery frames come with the territory. And, trying to push 2160p resolution through them is likely to overburden the host machine if it works at all.
What you can try:
Specify a data rate in the options to MediaRecorder, and specify something lower than the 2.5mbps default. This reduces the encoding machine's workload a bit.
new MediaRecorder (stream, {videoBitsPerSecond: 1000000} );
Reduce the resolution of the video. You can get better, but still not guaranteed-perfect, results with 720p resolution. This reduces the workload a lot.
Reduce the frame rate. This gives a little more time to code each frame, so dropped frames are less likely.
Upvotes: 1
Reputation: 136678
The frame rate should be specified on the input MediaStreamTrack
, e.g in the call to getUserMedia(constraints)
.
const constraints = {
video: { frameRate: { exact: 30 } }
};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
Though a too restrictive constraint like that has good chances of not being supported, so you might prefer request an initial ideal
value, and then try to force an exact one through MediaStreamTrack#applyConstraints()
.
const [track] = stream.getVideoTracks();
try {
await track.applyConstraints(constraints);
}
catch(err) {
// maybe try again with another value,
// e.g the one from track.getSettings().frameRate
}
Upvotes: 2