简体   繁体   中英

How can I change a video frame rate with FFmpeg, lossless and keeping the same total number of frames?

I've been searching for an answer here on Stack Overflow and googling everywhere... even though it seems like it should be a very simple command line to me, I just can't find an answer anywhere.

I would like to change the frame rate of a video from 23.976fps to 24fps with FFmpeg, lossless and keeping the total number of frames.

To make it simpler:

Let's say I have a 25fps video with a total lenght of 100 frames .

How can I change it's frame rate to 50fps , with FFmpeg , lossless and keeping the same total lenght of 100 frames ?

This was so far the best solution I came across with (which can be found here ):

Extract the frames as rawvideo:

ffmpeg -i input.mov -f rawvideo -b 50000000 -pix_fmt yuv420p -vcodec rawvideo -s 1920x1080 -y temp.raw

Recreate the video with new framerate:

ffmpeg -f rawvideo -b 50000000 -pix_fmt yuv420p -r 24 -s 1920x1080 -i temp.raw -y output.mov

Note 1: I had to remove "-b 50000000" when recreating the video with the new frame rate, in order to get it to work properly.

It did exactly what I intended it to do, but I'm still wondering if there is any simpler way to do this? I've tried to pipe them together in one line only, as suggested in the same post, but couldn't get it to work.

Note 2: Even though it does exactly what I wanted it to do, I've just later realized there is quality loss using this method, which I would prefer to avoid.

Thanks everyone in advance!

If your video codec is H.264/5, then this two-step method works, and is lossless.

#1 Demux to raw bitstream

ffmpeg -i in.mov -c copy in.264

#2 Remux with new framerate

ffmpeg -r 24 -i in.264 -c copy out.mov

For other codecs, if there's a raw bitstream format available, then it can be done without transcoding.

If transcoding is fine, the following single step works:

ffmpeg -r 24 -i in.mov -vsync 0 -c:v <codecname> out.mov 

Of course, you'll want to specify parameters like bitrate..etc to control quality.

The accepted answer drops the audio?

If that's true, I think the following python code did the same thing, just set a new FPS and rewrite video files:

import cv2 as cv
import time

time0 = time.time()
vid = cv.VideoCapture('input.flv')
fps = vid.get(cv.CAP_PROP_FPS)
frame_width = round(vid.get(cv.CAP_PROP_FRAME_WIDTH))
frame_height = round(vid.get(cv.CAP_PROP_FRAME_HEIGHT))
frame_count = round(vid.get(cv.CAP_PROP_FRAME_COUNT))

target_fps = fps
target_width = 800
target_height = frame_height * target_width // frame_width

out = cv.VideoWriter('output.mp4',
                     cv.VideoWriter_fourcc(*'avc1'), target_fps, (target_width,target_height))

time1 = time.time()
print('Time passed is %.3fs' % (time1 - time0))

ret, frame = vid.read()

i = 0
while ret:
    i += 1
    if frame_width != target_width:
        frame = cv.resize(frame, (target_width, target_height), interpolation=cv.INTER_LINEAR)
    out.write(frame)
    ret, frame = vid.read()

out.release()
vid.release()

print("COST: %.3fs" %(time.time() - time1))

Here I have also change the video scale to 800:-1.

Hope there is a better way to keep both all frames and audio.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM