Re-sampling H264 video to reduce frame rate while maintaining high image quality

85,584

Solution 1

A lot has changed since this posting in 2012. I am adding this answer for people like me who find this from the search engines. I had good luck with the following:

ffmpeg -y -i source.mp4 -r 25 -s 160x90 -c:v libx264 -b:v 3M -strict -2 -movflags faststart destination.mp4

Here’s a short explanation on what every parameter does:

  • -y : overwrite output files without asking
  • -i source.mp4 : input file name
  • -r 25 : output frame rate (in frames per second)
  • -s 160x90 : output frame size (in pixel) - inserts the scale video filter
  • -c:v libx264 : output video encoder
    • -c:v is short for -codec:v and -vcodec
  • -b:v 3M : video bitrate (in bit/s) passed to libx264 encoder
  • -strict -2 : governs standards compliance; -2 allows experimental features - required to enable native FFmpeg AAC audio encoder in builds older than version 2015-12-05, see here, AAC is now the default audio encoder.
  • -movflags faststart : move the index to the beginning of the output file (mov and mp4 format specific parameter)

For more details see the official documentation.

Solution 2

As Andy T indicated, you absolutely must re-encode the video, but that does not mean that the quality must be reduced in any noticeable manner.

First, ensure you are not using old software. Video codecs are a fast moving field with significant advanced every few weeks. x264 is currently the most advanced video encoder software available. It's probably what mplayer uses, but you can get the most recent real release from www.x264.nl

[Edit: HEVC and AV1 are now the most advanced technologies available. As I said, these are fast-moving fields!]

First, I would use VirtualDub to decompress to a lossless video type, which will make for a pretty large file. VirtualDub can also reduce the frame rate. See here.

Next, use this as the input to x264. I suggest you use helper software like Staxrip (put the most recent 32-bit 8-bits-per-channel x264 in StaxRip\Applications\x264.

If you want the absolute best quality with smallest file size where you are unlikely to notice the difference, use a command line like this (with x264):

x264 --preset placebo --tune film --crf 22 --level 4.1 --threads 1 --thread-input --sar 12:11 --output "<target>" "<source>"

Staxrip has options switch the preset to placebo, tune for film sources (assuming this isn't an animation of course), and to reduce thread count to 1.

You can change "--crf 22" to 21 for a larger, better quality video, but I've found CRF22 to be about the point where I have a very hard time noticing the difference, even when comparing frame-by-frame. Any change in the the other settings will probably reduce quality or increase file size without boost in quality. Increasing the number of threads will greatly improve encoding speed (on multi-core systems obviously), but will very slightly reduce quality (or in this case, because we are using CRF which is quality-based, will increase file size a little bit, like under 1% for 4 threads).

Most companies that encode video or that make products that encode video really have no idea what they are doing, and even if they did, they don't have the CPU power needed to do an encode with these settings, so in addition to the modest reduction in file size by frame rate reduction, you will also get a sharp drop in file size from using a smart encoder with the strictest settings.

If you want to make absolutely certain that the resulting video looks as close to VirtualDub's output as possible, no one can tell the difference using CRF17, but the file will be pretty large. You might as well just zip VirtualDub's output (well, not that bad!).

Share:
85,584
BrianTheLion
Author by

BrianTheLion

Updated on March 05, 2020

Comments

  • BrianTheLion
    BrianTheLion about 4 years

    Here's the mplayer output for a video of interest:

    br@carina:/tmp$ mplayer foo.mov 
    mplayer: Symbol `ff_codec_bmp_tags' has different size in shared object, consider re-linking
    MPlayer 1.0rc4-4.5.2 (C) 2000-2010 MPlayer Team
    mplayer: could not connect to socket
    mplayer: No such file or directory
    Failed to open LIRC support. You will not be able to use your remote control.
    
    Playing foo.mov.
    libavformat file format detected.
    [lavf] stream 0: video (h264), -vid 0
    [lavf] stream 1: audio (aac), -aid 0, -alang eng
    VIDEO:  [H264]  1280x720  24bpp  59.940 fps  2494.2 kbps (304.5 kbyte/s)
    ==========================================================================
    Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
    Selected video codec: [ffh264] vfm: ffmpeg (FFmpeg H.264)
    ==========================================================================
    ==========================================================================
    Opening audio decoder: [faad] AAC (MPEG2/4 Advanced Audio Coding)
    AUDIO: 44100 Hz, 2 ch, s16le, 128.0 kbit/9.07% (ratio: 15999->176400)
    Selected audio codec: [faad] afm: faad (FAAD AAC (MPEG-2/MPEG-4 Audio))
    ==========================================================================
    AO: [pulse] 44100Hz 2ch s16le (2 bytes per sample)
    Starting playback...
    Movie-Aspect is 1.78:1 - prescaling to correct movie aspect.
    VO: [vdpau] 1280x720 => 1280x720 Planar YV12
    

    I'd like to use ffmpeg, mencoder, or some other command-line video transcoder to re-sample this video to a lower framerate without loss of image quality. That is, each frame should remain as crisp as possible.

    Attempts

    ffmpeg -i foo.mov -r 25 -vcodec copy bar.mov
    • The target frame rate -- 25fps -- is achieved but individual frames are "blocky."
    mencoder -nosound -ovc copy foo.mov -ofps 25 -o bar.mov
    • Videos are effectively un-viewable.

    Help!

    This seems like a simple enough use case. I'm very surprised that obvious things are not working. Is there something wrong with my approach?

  • Emily L.
    Emily L. over 10 years
    --preset placebo is a waste of time. trac.ffmpeg.org/wiki/x264EncodingGuide#FAQ
  • Charles Burns
    Charles Burns over 10 years
    Placebo can slightly improve quality or slightly reduce stream size, depending on the source video. I get 0%-3% improvement, on average 1%. In a few rare cases, I've had a negative improvement, which is eliminated by reducing the motion estimation range. It does take MUCH longer to use the placebo preset, so it should only be used when quality or size are incredibly more important than encode time. Thread count can make much more of a difference than that between different presets, but again slightly affects quality (fewer threads = slightly better but slower).
  • BrianTheLion
    BrianTheLion about 9 years
    Thanks for the update! I don't have time to verify, but if others want to verify I am happy to accept your answer.
  • danijar
    danijar about 8 years
    Would be highly appreciated if you could explain those parameters.
  • bcattle
    bcattle almost 8 years
    Note that this also changes the length of the video, so if input the video has 10 frames, the output video will still have those same 10 frames, but the total run length will be longer or shorter.
  • motorbaby
    motorbaby almost 7 years
    Thanks! Used this to increase frame rate to 24 fps for Facebook on an animation that was 10 fps. Seems like what Vimeo might use for conversion.
  • m_j
    m_j over 6 years
    does this also re-encode and adjust the audio to stay in sync with the new video stream ?
  • CodeMed
    CodeMed over 6 years
    @mike The audio quality seemed unchanged after vs before. But it has been a long time since I used this.