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

3

40

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?

Forbidden answered 12/6, 2012 at 20:14 Comment(4)
Removing frames without decompressing the video is not that easy. In H.264 every frame is based on previous frames. If you just delete it, you won't be able to correctly decompress next frames. You need a very specific tool, which would merge the frames without completely decompressing them. I'm not sure if such thing exists. It's no surprise ffmpeg cannot do that.Hussy
Why do you want to reduce the frame rate? Note that with -r ffmpeg will simply drop or duplicate frames to your reach your desired value.Mutation
@LordNeckbeard: to reduce file size or to adapt to some decoder that doesn't handle so high framerateIndentation
@LordNeckbeard - The videos are part of a computer vision data set. Unfortunately, the team that compiled the data set recorded some at 25fps and some at 60fps. The algorithm that I'm testing is frame-rate sensitive, so I need to normalize the data to ensure consistent results.Forbidden
V
110

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.

Vanlandingham answered 21/1, 2015 at 17:54 Comment(6)
Thanks for the update! I don't have time to verify, but if others want to verify I am happy to accept your answer.Forbidden
Would be highly appreciated if you could explain those parameters.Sholom
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.Debark
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.Folie
does this also re-encode and adjust the audio to stay in sync with the new video stream ?Spectroscopy
@mike The audio quality seemed unchanged after vs before. But it has been a long time since I used this.Vanlandingham
W
6

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!).

Watteau answered 12/6, 2012 at 22:25 Comment(2)
--preset placebo is a waste of time. trac.ffmpeg.org/wiki/x264EncodingGuide#FAQSchutzstaffel
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).Watteau
I
0

You need to transcode your video in any case. Transcoding means you'll decode your stream, change framerate (drop frames in simple case) and then encode it again. Encoding configuration and even codec doesn't depend on how your video was encoded initially, so you can use anything suitable for your needs. If you need the highest possible quality, just encode with high profile as the first attempt. Then you can try to fine tune this even more playing with numerous h.264 encoding parameters.

Indentation answered 12/6, 2012 at 22:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.