MPDecimate is a command filter in FFmpeg. It is used to remove duplicate or near-duplicate frames from a video file. This can be useful in a variety of scenarios, such as reducing file size, removing camera shake, or removing duplicate frames caused by video encoding.
It’s worth noting that mpdecimate filter is a destructive filter. Meaning that the original frames are removed and not recoverable. Therefore, it’s advisable to make a backup of the original file before applying the filter.
The basic syntax of the command is as follows:
ffmpeg -i input.mp4 -vf mpdecimate output.mp4
The -i option is used to specify the input file, and the -vf option is used to apply a video filter. In this case, the filter is mpdecimate. The output file “output.mp4” is specified after the filter.
Let’s run MPDecimate filter on a sample video file and see how it performs.
The sample video is my screen recording, which has a lot of similar frames. The original video is 52 seconds length and 14,7 MB size.
Let’s run this command.
ffmpeg -i input.mp4 -vf mpdecimate output.mp4
And it didn’t change much. Except it decreased the video bitrate to default 1M, and video size become 6.9 MB. The video length stays the same 52 sec.
But some frames have been deleted.
Let’s add another filter which will change the timing of the frames, therefore we will see video length reduction.
In FFmpeg, the “setpts” filter is used to set the presentation timestamp of video frames. It changes the timing of the frames without altering their content.
ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB output_mpdecimate_simple.mp4
Now we see that video length reduced to 36 seconds vs 52 seconds in original video.
Now let’s play with MPDecimate parameters. And here is an interesting part, I’ve been reading the MPdecimate manual at least 10 times and it was hard to understand how it works. Let me try to make it easier for you. I will describe only some most important parameters to make it simpler.
Parameters “hi”, “lo”, “frac”.
FFMpeg manual states next:
Set the dropping threshold values.
Values for hi and lo are for 8×8 pixel blocks and represent actual pixel value differences, so a threshold of 64 corresponds to 1 unit of difference for each pixel, or the same spread out differently over the block.
A frame is a candidate for dropping if no 8×8 blocks differ by more than a threshold of hi, and if no more than frac blocks (1 meaning the whole image) differ by more than a threshold of lo.
Default value for hi is 64*12, default value for lo is 64*5, and default value for frac is 0.33.
Let’s start from the beginning. What is 8×8 pixel block. Here is zoomed representation.
So MPDecimate filter splits video frame into such blocks and then starts comparing those matching blocks between two consecutive frames. For example if we have two blocks like those:
Then, the difference would be more than 2. We can’t say exactly the difference number because we don’t know exact algorithm for difference calculations between two pixels.
So what is “hi” parameter in simple words? By setting “hi” paramater we set a number, this number relates only to one 8×8 block. Not for the whole video, only for a 8×8 block. We take one such block from first frame and then the same positioned block from second frame. Then we calculate a difference between them, by comparing pixel values. If the difference is greater than our “hi” parameter, then those frames stays in the video. But if the difference is lower than “hi”, this second frame is candidate for dropping.
By using this “hi” parameter we tell ffmpeg how important to us “fast activity” in the video. Even if it’s in a small area, relatively for the whole video. For example if we are watching sports with a lot of movements, then we need to use bigger “hi” parameter values in order to drop frames. Because in sports video we will have big difference between frames.
On the other hand, if we use screen recording, we will have low activity in the video, and if we take the same “hi” value from sports video, MPDecimate filter will drop almost all frames.
Ok, let’s move on to “lo” and “frac” parameter. We use those parameters to tell ffmpeg, how important for us to notice changes in large parts of video. How large? So “frac” is just a percentage value of all video size. Default value is 0.33, meaning it is 3rd part of the whole video. If we use “frac” 0.5, then it’s half of the video. When we set “lo” parameter, we tell ffmpeg that we want to drop frame only if less than half of it differs by more than “lo”
As an example, “frac”=0.5 (half video). If we are having 20% of video blocks which differ by more than “lo”, then we drop the frame. But if we are having 60% of blocks which differ by more than “lo”, then we are not going to drop the frame.
Obviously it make sense to make experiments and find optimal values.
Let’s start with next “hi” and “lo” values, 6400 and 1200. We will use default “frac” = 0.33.
ffmpeg -i input.mp4 -vf mpdecimate=hi=6400:lo=1200:frac=0.33 output_6400_1200_033.mp4
Here is the resulting video. It has the same video length as the original, but please notice that we have lost some frames, we can see it by mouse cursor strange movements. It stays on one place, and then suddenly appears in another place.
So MPDecimate filter deleted frames, and instead of removed frames placed duplicate first frame. And that’s why video has the same length. In order to shorten the video length by not copying those first frames, we will add another parameter to ffmpeg called “setpts”, here is the command:
ffmpeg -i input.mp4 -vf mpdecimate=hi=6400:lo=1200:frac=0.33,setpts=N/FRAME_RATE/TB output_6400_1200_033_setpts.mp4
And please check the result, now video is much shorter. It is 20 seconds now, versus 52 seconds of original video.
Please notice that we see less unimportant mouse movements and watch only most important actions. Like folder movement or browsing document.
As an experiment, let’s try remove more mouse movement, by adjusting “hi” parameter, we will set it higher.
ffmpeg -i input.mp4 -vf mpdecimate=hi=12800:lo=1200:frac=0.33,setpts=N/FRAME_RATE/TB output_12800_1200_033_setpts.mp4
Resulting video has 12 seconds length only. Also please notice that it’s not so comfortable to watch such video, so maybe we need to use lower values for “hi”.
When you work with MPDecimate filter try to play with parameters and find those optimal values which work specifically for your video.
I hope that tutorial was helpful!
By the way ChatGPT doesn’t know all the nuances of MPdecimate filter, so I’m afraid it won’t be helpful to use it. At least in ChatGPT 3.5 version 🙂 If you still have questions, please ping me at firstname.lastname@example.org. We are here at Trembit ready to help!