file size vs. preset goes the wrong direction

Issue #397 new
Former user created an issue

I see the following strange pattern whenever I use x265 encoding via ffmpeg: As I go to slower presets, the output file size increases. This is with both the latest git version, and the Debian (unstable) version. Inputs are various 720p or 1080p movies received via DVB-S2 or downloaded from the station directly (Mediathek). I'm running

for preset in medium slow slower veryslow; do /usr/bin/time -o "${preset}.time" ffmpeg -i ….mp4 -c:v libx265 -crf 26 -preset "${preset}" [audio] "out-${preset}.mp4" done

(CPU) time and output file size vs. preset is e.g. medium 19357.63user 492610613 slow 37010.42user 525615362 slower 93334.52user 546267556 veryslow 140979.16user 551318487

⇒ time taken goes up steeply, file size also increases in every step. As the documentation suggests, I cannot really say that there's a difference in picture quality between outputs.

The host architecture is Intel 64bit (various systems), the x265 versions I tested are "x265 (build 95)" from Debian unstable, and "x265 (build 156) - 2.7+20-3440a56acc78:[Linux][GCC 6.3.0][64 bit] 8bit" compiled myself. (The +20 is because of frequent merges of a Makefile patched locally, there are no differences in the code itself.)

For the latter version, the full settings as found in the output file are:

medium x265 (build 156) - 2.7+20-3440a56acc78:[Linux][GCC 6.3.0][64 bit] 8bit - H.265/HEVC codec - Copyright 2013-2018 (c) Multicoreware, Inc - http://x265.org - options: cpuid=1173503 frame-threads=3 wpp no-pmode no-pme no-psnr no-ssim log-level=2 bitdepth=8 input-csp=1 fps=25/1 input-res=1920x1080 interlace=0 total-frames=0 level-idc=0 high-tier=1 uhd-bd=0 ref=3 no-allow-non-conformance no-repeat-headers annexb no-aud no-hrd info hash=0 no-temporal-layers open-gop min-keyint=25 keyint=250 gop-lookahead=0 bframes=4 b-adapt=2 b-pyramid bframe-bias=0 rc-lookahead=20 lookahead-slices=6 scenecut=40 radl=0 no-intra-refresh ctu=64 min-cu-size=8 no-rect no-amp max-tu-size=32 tu-inter-depth=1 tu-intra-depth=1 limit-tu=0 rdoq-level=0 dynamic-rd=0.00 no-ssim-rd signhide no-tskip nr-intra=0 nr-inter=0 no-constrained-intra strong-intra-smoothing max-merge=2 limit-refs=3 no-limit-modes me=1 subme=2 merange=57 temporal-mvp weightp no-weightb no-analyze-src-pics deblock=0:0 sao no-sao-non-deblock rd=3 no-early-skip rskip no-fast-intra no-tskip-fast no-cu-lossless no-b-intra no-splitrd-skip rdpenalty=0 psy-rd=2.00 psy-rdoq=0.00 no-rd-refine no-lossless cbqpoffs=0 crqpoffs=0 rc=crf crf=26.0 qcomp=0.60 qpstep=4 stats-write=0 stats-read=0 ipratio=1.40 pbratio=1.30 aq-mode=1 aq-strength=1.00 cutree zone-count=0 no-strict-cbr qg-size=32 no-rc-grain qpmax=69 qpmin=0 no-const-vbv sar=1 overscan=0 videoformat=5 range=0 colorprim=2 transfer=2 colormatrix=2 chromaloc=0 display-window=0 max-cll=0,0 min-luma=0 max-luma=255 log2-max-poc-lsb=8 vui-timing-info vui-hrd-info slices=1 no-opt-qp-pps no-opt-ref-list-length-pps no-multi-pass-opt-rps scenecut-bias=0.05 no-opt-cu-delta-qp no-aq-motion no-hdr no-hdr-opt no-dhdr10-opt no-idr-recovery-sei analysis-reuse-level=5 scale-factor=0 refine-intra=0 refine-inter=0 refine-mv=0 no-limit-sao ctu-info=0 no-lowpass-dct refine-mv-type=0 copy-pic=1 max-ausize-factor=1.0 no-dynamic-refine

slow x265 (build 156) - 2.7+20-3440a56acc78:[Linux][GCC 6.3.0][64 bit] 8bit - H.265/HEVC codec - Copyright 2013-2018 (c) Multicoreware, Inc - http://x265.org - options: cpuid=1173503 frame-threads=3 wpp no-pmode no-pme no-psnr no-ssim log-level=2 bitdepth=8 input-csp=1 fps=25/1 input-res=1920x1080 interlace=0 total-frames=0 level-idc=0 high-tier=1 uhd-bd=0 ref=4 no-allow-non-conformance no-repeat-headers annexb no-aud no-hrd info hash=0 no-temporal-layers open-gop min-keyint=25 keyint=250 gop-lookahead=0 bframes=4 b-adapt=2 b-pyramid bframe-bias=0 rc-lookahead=25 lookahead-slices=4 scenecut=40 radl=0 no-intra-refresh ctu=64 min-cu-size=8 rect no-amp max-tu-size=32 tu-inter-depth=1 tu-intra-depth=1 limit-tu=0 rdoq-level=2 dynamic-rd=0.00 no-ssim-rd signhide no-tskip nr-intra=0 nr-inter=0 no-constrained-intra strong-intra-smoothing max-merge=3 limit-refs=3 limit-modes me=3 subme=3 merange=57 temporal-mvp weightp no-weightb no-analyze-src-pics deblock=0:0 sao no-sao-non-deblock rd=4 no-early-skip rskip no-fast-intra no-tskip-fast no-cu-lossless no-b-intra no-splitrd-skip rdpenalty=0 psy-rd=2.00 psy-rdoq=1.00 no-rd-refine no-lossless cbqpoffs=0 crqpoffs=0 rc=crf crf=26.0 qcomp=0.60 qpstep=4 stats-write=0 stats-read=0 ipratio=1.40 pbratio=1.30 aq-mode=1 aq-strength=1.00 cutree zone-count=0 no-strict-cbr qg-size=32 no-rc-grain qpmax=69 qpmin=0 no-const-vbv sar=1 overscan=0 videoformat=5 range=0 colorprim=2 transfer=2 colormatrix=2 chromaloc=0 display-window=0 max-cll=0,0 min-luma=0 max-luma=255 log2-max-poc-lsb=8 vui-timing-info vui-hrd-info slices=1 no-opt-qp-pps no-opt-ref-list-length-pps no-multi-pass-opt-rps scenecut-bias=0.05 no-opt-cu-delta-qp no-aq-motion no-hdr no-hdr-opt no-dhdr10-opt no-idr-recovery-sei analysis-reuse-level=5 scale-factor=0 refine-intra=0 refine-inter=0 refine-mv=0 no-limit-sao ctu-info=0 no-lowpass-dct refine-mv-type=0 copy-pic=1 max-ausize-factor=1.0 no-dynamic-refine

slower x265 (build 156) - 2.7+20-3440a56acc78:[Linux][GCC 6.3.0][64 bit] 8bit - H.265/HEVC codec - Copyright 2013-2018 (c) Multicoreware, Inc - http://x265.org - options: cpuid=1173503 frame-threads=3 wpp no-pmode no-pme no-psnr no-ssim log-level=2 bitdepth=8 input-csp=1 fps=25/1 input-res=1920x1080 interlace=0 total-frames=0 level-idc=0 high-tier=1 uhd-bd=0 ref=4 no-allow-non-conformance no-repeat-headers annexb no-aud no-hrd info hash=0 no-temporal-layers open-gop min-keyint=25 keyint=250 gop-lookahead=0 bframes=8 b-adapt=2 b-pyramid bframe-bias=0 rc-lookahead=30 lookahead-slices=4 scenecut=40 radl=0 no-intra-refresh ctu=64 min-cu-size=8 rect amp max-tu-size=32 tu-inter-depth=2 tu-intra-depth=2 limit-tu=4 rdoq-level=2 dynamic-rd=0.00 no-ssim-rd signhide no-tskip nr-intra=0 nr-inter=0 no-constrained-intra strong-intra-smoothing max-merge=3 limit-refs=2 limit-modes me=3 subme=3 merange=57 temporal-mvp weightp weightb no-analyze-src-pics deblock=0:0 sao no-sao-non-deblock rd=6 no-early-skip rskip no-fast-intra no-tskip-fast no-cu-lossless b-intra no-splitrd-skip rdpenalty=0 psy-rd=2.00 psy-rdoq=1.00 no-rd-refine no-lossless cbqpoffs=0 crqpoffs=0 rc=crf crf=26.0 qcomp=0.60 qpstep=4 stats-write=0 stats-read=0 ipratio=1.40 pbratio=1.30 aq-mode=1 aq-strength=1.00 cutree zone-count=0 no-strict-cbr qg-size=32 no-rc-grain qpmax=69 qpmin=0 no-const-vbv sar=1 overscan=0 videoformat=5 range=0 colorprim=2 transfer=2 colormatrix=2 chromaloc=0 display-window=0 max-cll=0,0 min-luma=0 max-luma=255 log2-max-poc-lsb=8 vui-timing-info vui-hrd-info slices=1 no-opt-qp-pps no-opt-ref-list-length-pps no-multi-pass-opt-rps scenecut-bias=0.05 no-opt-cu-delta-qp no-aq-motion no-hdr no-hdr-opt no-dhdr10-opt no-idr-recovery-sei analysis-reuse-level=5 scale-factor=0 refine-intra=0 refine-inter=0 refine-mv=0 no-limit-sao ctu-info=0 no-lowpass-dct refine-mv-type=0 copy-pic=1 max-ausize-factor=1.0 no-dynamic-refine

veryslow x265 (build 156) - 2.7+20-3440a56acc78:[Linux][GCC 6.3.0][64 bit] 8bit - H.265/HEVC codec - Copyright 2013-2018 (c) Multicoreware, Inc - http://x265.org - options: cpuid=1173503 frame-threads=3 wpp no-pmode no-pme no-psnr no-ssim log-level=2 bitdepth=8 input-csp=1 fps=25/1 input-res=1920x1080 interlace=0 total-frames=0 level-idc=0 high-tier=1 uhd-bd=0 ref=5 no-allow-non-conformance no-repeat-headers annexb no-aud no-hrd info hash=0 no-temporal-layers open-gop min-keyint=25 keyint=250 gop-lookahead=0 bframes=8 b-adapt=2 b-pyramid bframe-bias=0 rc-lookahead=40 lookahead-slices=0 scenecut=40 radl=0 no-intra-refresh ctu=64 min-cu-size=8 rect amp max-tu-size=32 tu-inter-depth=3 tu-intra-depth=3 limit-tu=4 rdoq-level=2 dynamic-rd=0.00 no-ssim-rd signhide no-tskip nr-intra=0 nr-inter=0 no-constrained-intra strong-intra-smoothing max-merge=4 limit-refs=1 limit-modes me=3 subme=4 merange=57 temporal-mvp weightp weightb no-analyze-src-pics deblock=0:0 sao no-sao-non-deblock rd=6 no-early-skip rskip no-fast-intra no-tskip-fast no-cu-lossless b-intra no-splitrd-skip rdpenalty=0 psy-rd=2.00 psy-rdoq=1.00 no-rd-refine no-lossless cbqpoffs=0 crqpoffs=0 rc=crf crf=26.0 qcomp=0.60 qpstep=4 stats-write=0 stats-read=0 ipratio=1.40 pbratio=1.30 aq-mode=1 aq-strength=1.00 cutree zone-count=0 no-strict-cbr qg-size=32 no-rc-grain qpmax=69 qpmin=0 no-const-vbv sar=1 overscan=0 videoformat=5 range=0 colorprim=2 transfer=2 colormatrix=2 chromaloc=0 display-window=0 max-cll=0,0 min-luma=0 max-luma=255 log2-max-poc-lsb=8 vui-timing-info vui-hrd-info slices=1 no-opt-qp-pps no-opt-ref-list-length-pps no-multi-pass-opt-rps scenecut-bias=0.05 no-opt-cu-delta-qp no-aq-motion no-hdr no-hdr-opt no-dhdr10-opt no-idr-recovery-sei analysis-reuse-level=5 scale-factor=0 refine-intra=0 refine-inter=0 refine-mv=0 no-limit-sao ctu-info=0 no-lowpass-dct refine-mv-type=0 copy-pic=1 max-ausize-factor=1.0 no-dynamic-refine

Comments (12)

  1. JPT

    I can confirm this behavior.

    1,7G ultrafast.m4v 39 fps, 2557,03 kb/s, Avg QP:24,87
    1,8G veryfast.m4v 34 fps, 2670,32 kb/s, Avg QP:24,94
    1,8G faster.m4v 34 fps, 2672,08 kb/s, Avg QP:24,94
    1,8G fast.m4v 30 fps, 2691,99 kb/s, Avg QP:24,94
    2,1G medium.m4v 28 fps, 3168,59 kb/s, Avg QP:24,55
    3,0G slow.m4v 11 fps, 4597,39 kb/s, Avg QP:24,55

    What does Average QP mean?

    The minimal FPS difference between all runs from ultrafast til medium is caused by the denoise filter, see next comment.

    System: Ubuntu 19.4 64 bit
    libx265 from Ubuntu 19.10 repo, version 3.1.1-2, similar results with libx265-165/disco,now 2.9-4
    Handbrake from official snapshot repo version 20190914125452-3e00e3b-master, similar results with handbrake/disco 1.2.2+ds1-1 from ubuntu repo

  2. Herbert Thomson

    Former user created an issue 2018-04-06”

    Since then no response from developers. Sad. Especially since user reports “I cannot really say that there's a difference in picture quality”, but filesize increases dramatically, there must be something fundamentally broken.

    This is a core functionality. The promise is if you choose a slower preset, your efficiency will increase. But we can see here that the opposite is the case. x265 is broken in it’s core. The slow(er) presets will waste up to 50% of your diskspace for no good reason…

    I can’t believe there is such a core issue that has been ignored by developers for years. Probably it was more important to cheat top benchmark results instead of looking at real world cases.

    Now since we learned that x265 encoding efficiency is basically fake, what should we do? Use x264? Or AV1?

  3. JPT

    x265 is broken in it’s core.

    And this for years. At least since version 2.7 of Feb 2018, as stated in the first comment. What version was build 95 which was referenced above?
    According to my tests, this problem already existed in 2.9.

    This bug should be top priority!

    This time without any filter and with Tune:none.

    Same problem.

    You know what? I think Ratefactor/ConstantQuality is broken. It’s the only cause I can think of that wouldn’t render x265 completly broken.

    1110004491 bytes, 65,91 fps, 1528,06 kb/s, Avg QP:27,83 0ultrafast.mkv
    1350211498 bytes, 57,62 fps, 1894,39 kb/s, Avg QP:27,13 1superfast.mkv
    1737263411 bytes, 40,64 fps, 2484,71 kb/s, Avg QP:25,21 2veryfast.mkv

    more still running

  4. Selur

    Seems like a misunderstanding what crf (=constant rate factor) is, is not some magic quality metric over different settings.
    Assuming all other settings are fixed crf will try to keep the quality at a perceived constant level, as soon as you change anything this does not hold true. So for example the quality of a re-encode once done with crf 18 without b-frames and once with crf 18 and b-frames will differ.
    So it is to be expected that when changing presets both quality and file size will differ.

    To compare re-encodes of a source you normally either:
    a. encode to a fixed target size and do a visual comparision
    or
    b. use encode to a fixed quality (<- given by some specific metric, e.g. all reencodes must have the same PSNR value) and then compare the file size.

    So to see the effect of the presets/tune options, encode 2pass to a fixed size and compare the output of those encodes when only changing the presets.

  5. JPT

    Well. If you say so.

    x265 is not my project. You may continue to define common sense as wrong and the odd behavior of x265 as correct. But I won’t use x265 any more. Instead I go back to x264.

    btw, I have to reference this https://bitbucket.org/multicoreware/x265/issues/434/about-the-performance-of-x265_28-compared

    as it shows another example where a convention simply is ignored to define your position as the better one. Even when thousands of experts have considered “objectivley measureable figures” the only way that makes sense.

    thanks for your time and effort.

    bye

  6. Selur

    I just wanted to help out and point out that to me it looked like you are looking into a none-issue since you started from a wrong point of view what crf does and means. If you are happy with x264 stick with it. 🙂

  7. Herbert Thomson

    It seems arbitrary that when you choose a different preset the way the quality is evaluated changes. Does not make any sense. There must be some model that defines quality, and when I allow x265 to use more processing power, it should be able to achieve the same quality (under whatever metric you choose) with less bits.

    When x265 decides that with the slower presets, it actually needs more space to achieve the same quality, and if I believe you that encoding efficiency did not decrease, that means that x265 suddenly changes the way the quality is measured. The quality measure then somehow depends on the encoding settings. I think this is bad design. It reminds me of some old video games where the in-game speed depends on the frames per second and on modern computers the game suddenly was way to fast. It is just bad design and things that should be independent from each other are interconnected in a strange way.

  8. Selur

    You are doing it again. CRF does not measure quality, when encoding with a constant rate factor you tell the encoder to try to stick to a constant level between needed bitrate and adjustments due to frame choice etc. This does not mean you are telling x265 (same goes for x264 btw.) to stick to a fixed quality.
    The description says crf tries to archive a ‘uniform quality’ which isn’t the same as a constant quality and it does not mean that the quality is an objective quality measurement. 😉

    → I agree:
    a. the description does often confuse folks which have no clue what ‘rate factor’, ‘rate control’ and ‘rate distribution’ really does.
    b. it would be interesting to have a rate control mode which would aim to archive an average value X with a given quality metric (e.g. VMAF, NIQE, PSNR, MSE, MSAD, SSIM, VQM,…). This would do what you think crf does, but crf is not like VQMF&Co.
    c. it’s sad to see that the x265 team hasn’t some good documentation so that users can easier understand what crf does and is.

    If you know what quantization does and thus quant using constant quantizer mode is, you understand that using a constant quantizer does not mean you are choosing a constant quality, you are just setting some kind of max error value. CRF now is a try to archive a constant quality by ‘optimizing’ QP mode that is by varying quantizers for somewhat better quality.
    CRFs mode produces a constant quality in the sense that it tries to keep an fixed maximum visual loss during quantization while trying to dampen visual losses.

  9. Deepthi Nandakumar

    Very important discussion.

    @Selur, your points about CRF are correct. These would hold if different videos or same video at different resolutions etc. were being compared. However, for the simple commandline that the original author used “ffmpeg -i ….mp4 -c:v libx265 -crf 26 -preset "${preset}" [audio] "out-${preset}.mp4” - this should give monotonically reducing file sizes and/or increasing quality. This is not a property of CRF, this is a property of how the speed presets “should” be crafted. So, the results the user is reporting indicates that the speed presets are not crafted correctly today.

    The more important statement, that has been made is that “there is no quality increase”. Can you please confirm this using objective metrics - PSNR, SSIM, VMAF etc. If this is true, this should definitely be investigated - it means there are encoding parameters/algorithms enabled in the slower presets that are literally doubling filesizes for no change in quality.

  10. Herbert Thomson

    I have found this very interesting comment: https://forum.doom9.org/showpost.php?p=1885640&postcount=11

    This perfectly explains the behavior we observe. The issue is that if we choose a different preset, this very much changes the meaning of the CRF values itself, they will have a different meaning for different encoder settings, thus of course file size will be different.

    It is indeed as I said before: The encoder settings and the quality measure are interconnected in a strange way.

    If I can give x265 devs one advice: At least you should disconnect encoder settings and quality measure. Howsoever you define your metric doesn't matter. I got that it is not an accurate way to measure quality, it just measure quantization error so whatsoever. Yeah, that’s ok. Just make sure that it is, under all circumstances, calculated in the same way. From an end-user perspective this is what you implicitly assume to be true, and it is very hard to imagine why this should not be the case. Probably only the best experts on this topic would understand this.

  11. Log in to comment