How to slowdown or speed up a video using FFmpeg and Yuvfps
I was watching a bball Mix yesterday, a complete Kobe saga with a great background music. I have never made a video mix, but probably the things I like in a good mix are the involvement of video effects at the right time - slowing down the video at a dunk shot etc.
I am sure there would be some GUI tools capable of enabling such effects, but as a FFmpeg user and an unprofessional , I thought "lets see if the superstar is capable of doing it?". The answer is almost yes. We actually use one more tool, yuvfps, to make it work.
Let me first introduce the mjpeg-tools. They are a collection of programs for recording, playback, small video editing and similar tasks. Yuvfps is a part of this package. It is used to change the frame rate of a video.
Slowing down the video (Theory)
So, when I finally ran the command, fortunately it worked, but it took me a while to understand how it actually happened. Ironically, the command to slow down a clip, slowed me down .
Anyway, I hope we are all aware of the frame-rate. Lets say we have a video of 60 fps i.e 60 frames per second. So, if we can somehow only show 30 frames per second, the video will slow down to half the original speed. We can ofcourse, change the frame-rate of the video to half, but while doing that FFmpeg drops frames, which is not what we want.
If only we could convince the tool to assume the frame rate of the actual file to be 30 fps and then generate a new file, we couldactually get a slowed down video without any dropped frames. Yuvfps comes into play here.
Yuvfps comes bundled in mjpegtools. Either click this link or run this command to install mjpegtools.
[shredder12]$ sudo apt-get install mjpegtools #on Ubuntu/Debian
[root]# yum install mjpegtools #on Fedora/RedHat
Slow Down the Video
This is the command to slow down the video from 60 to 30fps.
[shredder12]$ ffmpeg -i video.avi -f yuv4mpegpipe - | yuvfps -s 30:1 -r 30:1 | ffmpeg -f yuv4mpegpipe -i - -b 28800k slow.avi
The '-' used is to pipe the output file for yuvfps and then to accept the input from pipe. 30:1 means 30 fps. In a similar way you can use it to define other frame rates, e.g 50:1 for 50fps.
The output file by default is very poor in quality. Although the size may increase but if you need a better quality video, do set the -b flag accordingly.
Speed up video
In a similar way, we can speed up the video by increasing the frame rate. e.g using 120:1 will double the speed.
[shredder12]$ ffmpeg -i video.avi -f yuv4mpegpipe - | yuvfps -s 120:1 -r 120:1 | ffmpeg -f yuv4mpegpipe -i - -b 28800k slow.avi
Issues to be fixed
If you try these methods, you will notice "no audio". I still don't know how to fix this, but if anyone knows what am I missing here, do leave a comment.
And I even tried to do it solely using ffmpeg, using the following command. (30fps -> 15)
[shredder12]$ ffmpeg -i input.mp4 -f yuv4mpegpipe - | ffmpeg -f yuv4mpegpipe -r 15 -i - -b 28800k output.mp4
But it resulted in the same speed, probably dropped the frames while reducing the frame rate. I still think ffmpeg could solely be able to alter video speed, but can't figure out the problem here.