1

Basically, I want to force change the frame rate of a file that is not encoded using H.264. With H.264 I can do the following:

# Assume I want to take a 30FPS file and make it 60FPS, effectively doubling the speed.

# Extract the H264 stream from the source file to a raw H264 stream
ffmpeg -i source.mp4 -map 0:v -vcodec copy -bsf:v h264_mp4toannexb source-video.h264

# Force FFMPEG to regenerate the PTS values for the H264 stream
ffmpeg -fflags +genpts -r 60 -i source-video.h264 -vcodec copy output.mp4

This technique is documented by FFmpeg themselves and has already been explained here on Super User and is also pretty much the result you'll find if you look this up on Google.

However, assume my source stream is not in H.264 or H.265 format, and thus I can't use that sequence of commands. For example, suppose I have an FFV1 stream (from an archival source), or an MPEG2 stream (from a DVD), or even an MPEG1 stream (from a VideoCD etc). Assume I want to keep the video in its original codec, thus encoding to H.264, doing the framerate conversion, then converting back to the original format is two extra generations of lossy compression which definitely does not qualify as "without re-encoding".

I've tried using vsync-drop and setpts on other codecs (like FFV1) and it doesn't seem to work:

# source is FFV1 at 30fps
# this produces a 1.5 second output for 60 seconds of video
# output is only the first few frames of source, still at 30fps
# ffprobe also shows 30fps for the output file

ffmpeg -vsync drop -fflags +genpts -i ffv1video.mkv -map 0:v -c copy ffv1fastvideo.mkv 

# removing -vsync drop results in an identical output file
ffmpeg -fflags +genpts -i ffv1video.mkv -map 0:v -c copy -r 60 ffv1fastvideo.mkv

# adding a frame rate to the input changes nothing
ffmpeg -r 60 -vsync drop -fflags +genpts -i ffv1video.mkv -map 0:v -c copy -r 60 ffv1fastvideo.mkv

# you can't use -vf setpts=... if you are using -c copy

All of the above apply if I'm also using a codec like mpeg2 or whatever. Basically I just want to regenerate the PTS on each frame without re-encoding the entire stream.

Seems like this is something FFmpeg should be able to do on streams other than h.264 and h.265 - can I do it?

fdmillion
  • 1,349
  • 2
  • 18
  • 27
  • 1
    See https://superuser.com/q/1454645/ – Gyan Nov 23 '21 at 15:28
  • The `-itsscale` option looks useful. It might be tough to get precisely the desired framerate but it should be within tolerance. I'll give it a try and report back. – fdmillion Nov 24 '21 at 09:57

1 Answers1

0

You can do this using the bitstream filter setts. This works because while you can't use normal filters with codec copy (-c:v copy) since they work on the decoded video stream, you can use bitstream filters which work on the encoded stream.

I have a more detail post about it here: Change framerate in ffmpeg without reencoding

goweon
  • 1,693
  • 2
  • 19
  • 21
  • Please do not post the same answer to multiple questions. If the same information really answers both questions, then one question (usually the newer one) should be closed as a duplicate of the other. You can indicate this by [voting to close it as a duplicate](https://superuser.com/help/privileges/close-questions) or, if you don't have enough reputation for that, [raise a flag](https://superuser.com/help/privileges/flag-posts) to indicate that it's a duplicate. Otherwise tailor your answer to this question and don't just paste the same answer in multiple places. – DavidPostill Apr 29 '23 at 21:25