使用 ffmpeg 改变帧率

我试图转换一个视频剪辑(MP4,yuv420p)从30 fps 到24 fps。帧数是正确的,所以我的输出应该从20分钟每秒30帧改为25分钟每秒24帧。其他一切都应该保持不变。

尽可能尝试所有我尝试与 ffmpeg 转换帧速率,但改变帧的数量,以保持相同的持续时间或改变持续时间,而不改变帧速率。

所以我一直在尝试

ffmpeg -y -r 30 -i seeing_noaudio.mp4 -r 24 seeing.mp4

(我在 windows 上这样做,但通常是在 linux 上)。这转换帧率,但下降帧,所以总持续时间是不变的。

或者说我试过了

ffmpeg -y -i seeing_noaudio.mp4 -filter:v "setpts=1.25*PTS" seeing.mp4

这会改变持续时间,但不会改变帧率。

当然,我应该能够使用单个 ffmpeg 命令完成这项工作,而不必重新编码,甚至不必像有些人建议的那样返回到原始的原始框架。

救命啊

208162 次浏览

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

You may consider using fps filter. It won't change the video playback speed:

ffmpeg -i <input> -filter:v fps=fps=30 <output>

Worked nice for reducing fps from 59.6 to 30.

In general, to set a video's FPS to 24, almost always you can do:

With Audio and without re-encoding:

# Extract video stream
ffmpeg -y -i input_video.mp4 -c copy -f h264 output_raw_bitstream.h264
# Extract audio stream
ffmpeg -y -i input_video.mp4 -vn -acodec copy output_audio.aac
# Remux with new FPS
ffmpeg -y -r 24 -i output_raw_bitstream.h264 -i output_audio.aac -c copy output.mp4

If you want to find the video format (H264 in this case), you can use FFprobe, like this

ffprobe -loglevel error -select_streams v -show_entries stream=codec_name -of default=nw=1:nk=1 input_video.mp4

which will output:

h264

Read more in How can I analyze file and detect if the file is in H.264 video format?


With re-encoding:

ffmpeg -y -i input_video.mp4 -vf -r 24 output.mp4

You can try for example (to convert from 25 fps to 24 fps)

ffmpeg -itsscale 1.0416667 -i "your input file" -vcodec copy "output file"

the itsscale value of 1.0416667 is 25/24 as a float variable for ffmpeg (0.1234567 is the float values format - don't use 1.04166666666666666667 or a double value : note that you can't use the expression/formula "25/24" here) This will scale the frame rate times from 25 to 24 fps, keeping the same number of frames, but lengthening the video by 1.0416667 .

going from 23.976 to 24 or going from 29.97 to 30 this value would be 0.999)

If you have audio you would include an audio filter to rescale the audio without a pitch change by changing the tempo using the atempo settings, you should include a compressor and bit rate as well. For subtitles, you just need to include the -codec:s

so we would have

ffmpeg -itsscale 1.0416667 -i "input file" -filter:a atempo="24/25" -codec:a ac3 -b:a 640k -vcodec copy -codec:s copy "output file"

where I used the ac3 audio codec at a bitrate of 640K and the expression "24/25" which is allowed here :NOTE: the 24/25 is the inverse of the itsscale value of 25/24(=1.0416667)

Note: if you have more than 1 stream, (video or audio or subtitle) you may need to include the -map i:v:o (or 0:a:0 or 0:s:0 where 'i' is the input stream number and 'o' is the stream track to output