Drop every even or odd frames using FFmpeg?
To work accurately, first convert the video to RAW YUV bitstream (if it is not already) by:
ffmpeg -i input.mp4 -an -vcodec rawvideo -pix_fmt yuv420p rawbitstream.yuv
Next step: The select
filter takes an expression, where n
is the frame number.
ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="mod(n-1\,2)" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an odd.yuv
ffmpeg -r 2 -s WxH -i rawbitstream.yuv -filter:v select="not(mod(n-1\,2))" \
-c:v rawvideo -r 1 -format rawvideo -pix_fmt yuv420p -an even.yuv
To have ffmpeg
not duplicate frames, you have to force half of the framerate of your input - so you set "2" as the input and "1" to the output. Don't forget to replace the WxH with the actual dimensions of your clip because the raw bitstream doesn't have a header that carries this information.
Instead of the above, another possibility would be to add the setpts
filter to set new timestamps for the output. But be careful since it drops frames not accurately. Here, 25 is the actual output frame rate you want:
ffmpeg -i input.mp4 -filter:v select="mod(n-1\,2)",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an odd.yuv
ffmpeg -i input.mp4 -filter:v select="not(mod(n-1\,2))",setpts="N/(25*TB)" \
-c:v rawvideo -r 12.5 -format rawvideo -pix_fmt yuv420p -an even.yuv
You can of course choose another pixel format (any of ffmpeg -pix_fmts
). Make sure that when reading the file you know the pixel size and pixel format:
ffmpeg -f rawvideo -s:v 1280x720 -pix_fmt yuv420p input.yuv …
If your ffmpeg was built with the AviSynth flag, then I believe you can pass an .avs
file.
You can check by running ffmpeg
and looking for --enable-avisynth
in the configuration data.
If it's there you can use it like so: ffmpeg -i blahEven.avs blahEven.yuv
.
Where blahEven.avs
is simply:
ffvideosource("blah.yuv").SelectEven()
For odd frames, use SelectOdd()
.
For more advanded usage, see the SelectEvery documentation.