0
votes

I'm trying to create videos with a very specific handful of requirements using FFMPEG:

  • Must have a very low (ideally less than 0.5 seconds) keyframe rate
  • Must have a moderately low (~1Mbps) bitrate
  • Must run at a reasonable (~24fps) framerate
  • Must have a width multiple of 4
  • Must not have any B-frames
  • Must be H.264 baseline encoded
  • Must be FLV

Encoding speed is of no concern. If it takes 2 minutes to encode 1 second of video, that's absolutely fine. What matters is that the output retains quality at the lowest possible bitrate.

To this effect I currently have the following FFMPEG command:

ffmpeg \
    -fflags +genpts \
    -i big_buck_bunny_1080p_stereo.avi \
    -vf "scale=trunc(360*iw/ih/4)*4:360" \
    -vf "settb=1/1000" \
    -r 24 \
    -g 6 \
    -keyint_min 6 \
    -force_key_frames "expr:gte(t,n_forced/4)"\
    -c:v libx264 \
        -preset veryslow \
        -tune zerolatency \
        -profile:v baseline \
        -pix_fmt yuv420p \
    -b:v 1000k \
    -c:a speex \
        -ar 16000 \
        -ac 1 \
    -b:a 64k \
    -f flv bbb_lo.flv

I wish to experiment with various encoding options (me_method, subq, etc) to see how they all affect quality and bitrate. Before that, though, I've got an immediate quality issue to address with the command above.

See the video here on YouTube

I've clipped just a portion of the video that really demonstrates the issue. When an area of the screen undergoes very slight changes in color, there are no motion vectors. This means that certain sections of the video go un-updated until the next keyframe. This can be seen strongly in the tree on the left at the beginning of the video or in the bunny while he's still asleep. If a viewer were staring at certain regions of the screen it may look like the video is only running at 4 frames per second (my keyframe rate) even though the video is actually running at 24 frames per second -- it just isn't updating the entire screen.

I'd be okay if these areas of the screen became heavily blurred so long as the motion is preserved. Doing a bit of research I thought that the options -flags2 -fastpskip would fix this, however this option is not working for me:

[libx264 @ 0x55b63e32c760] [Eval @ 0x7ffea2a7a830] Undefined constant or missing '(' in 'fastpskip'
[libx264 @ 0x55b63e32c760] Unable to parse option value "fastpskip"
[libx264 @ 0x55b63e32c760] Error setting option flags2 to value -fastpskip.

How can I fix this to preserve motion at the cost of image quality?

1
ffmpeg's flags2 fastpskip was removed a long time ago. You could replace -preset veryslow with -preset placebo, which contains it (see x264 --fullhelp). - micha137
One can just set it using x264-params. - Gyan

1 Answers

1
votes

The motion vectors are computed by the encoder (x264), not ffmpeg. Your video remains 1080p, not 360p, for which the given bitrate is very low, so during quantization, subtle changes will get flattened out.

There can only one simple filtergraph per output-stream, so

-vf "scale=trunc(360*iw/ih/4)*4:360" \
-vf "settb=1/1000" \

has to become

-vf "scale=trunc(360*iw/ih/4)*4:360,settb=1/1000" \

else only the timebase filter is applied.

For a GOP size of 6, you can also skip keyint and forced KFs.