I am trying to convert a video clip (MP4, yuv420p) from 30 fps to 24 fps. The number of frames is correct so my output should change from 20 minutes at 30fps to 25 minutes at 24fps. Everything else should remain the same.
Try as I might everything I try with ffmpeg converts the frame rate but changes the number of frames to keep the same duration or changes the duration without altering the framerate.
So I have been typically trying things like;
ffmpeg -y -r 30 -i seeing_noaudio.mp4 -r 24 seeing.mp4
(I'm doing this on windows but normally would be on linux). That converts the framerate but drops frames so the total duration is unaltered.
Or I have tried
ffmpeg -y -i seeing_noaudio.mp4 -filter:v "setpts=1.25*PTS" seeing.mp4
Which changes the duration but not the framerate.
Surely I should be able to do this with a single ffmpeg command without having to reencode or even as some people suggested going back to the original raw frames.
Help please
With re-encoding:
ffmpeg -y -i seeing_noaudio.mp4 -vf "setpts=1.25*PTS" -r 24 seeing.mp4
Without re-encoding:
First step - extract video to raw bitstream
ffmpeg -y -i seeing_noaudio.mp4 -c copy -f h264 seeing_noaudio.h264
Remux with new framerate
ffmpeg -y -r 24 -i seeing_noaudio.h264 -c copy seeing.mp4
Simply specify the desired framerate in "-r " option before the input file:
ffmpeg -y -r 24 -i seeing_noaudio.mp4 seeing.mp4
Options affect the next file AFTER them. "-r" before an input file forces to reinterpret its header as if the video was encoded at the given framerate. No recompression is necessary. There was a small utility avifrate.exe to patch avi file headers directly to change the framerate. ffmpeg command above essentially does the same, but has to copy the entire file.
To the best of my knowledge you can't do this with ffmpeg
without re-encoding. I had a 24fps file I wanted at 25fps to match some other material I was working with. I used the command ffmpeg -i inputfile -r 25 outputfile
which worked perfectly with a webm,matroska input and resulted in an h264, matroska output utilizing encoder: Lavc56.60.100
You can accomplish the same thing at 6fps but as you noted the duration will not change (which in most cases is a good thing as otherwise you will lose audio sync). If this doesn't fit your requirements I suggest that you try this answer although my experience has been that it still re-encodes the output file.
For the best frame accuracy you are still better off decoding to raw streams as previously suggested. I use a script for this as reproduced below:
#!/bin/bash
#This script will decompress all files in the current directory, video to huffyuv and audio to PCM
#unsigned 8-bit and place the output #in an avi container to ease frame accurate editing.
for f in *
do
ffmpeg -i "$f" -c:v huffyuv -c:a pcm_u8 "$f".avi
done
Clearly this script expects all files in the current directory to be media files but can easily be changed to restrict processing to a specific extension of your choosing. Be aware that your file size will increase by a rather large factor when you decompress into raw streams.
You can use this command and the video duration is still unaltered.
ffmpeg -i input.mp4 -r 24 output.mp4