CRF diffs relatively bit rate diffs formula

Issue #339 new
Former user created an issue

CRF1 - CRF setting which was in first/prev encode, bitrate1 - bitrate setting in kbps which has result encoded file in first/prev encode, CRF2 and bitrate2 - choose what to calculate and set it to null value and to which relative parameter to make a calculation and set it to numeric value.

(function () {
  // ********************************
  //   x265 bitrate or CRF predictor based on first encode.
  //   version 0.0.0
  //   RuTracker.org, LiveM
  // ********************************

  let obj = {

    // first/previos encode. this is calcutation basis
    CRF1: 23.2,
    bitrate1: 3500, //kbps

    // set one property to null and another one the a numeric value you want
    CRF2: null,
    bitrate2: 3000, //kbps
  };

  function calcNewCRForBitrate(obj) {
    if ((obj.CRF2 && obj.bitrate2) || (!obj.CRF2 && !obj.bitrate2)) {
      return 'Error: Please, set one unknown parameter to null value and another one to a number which the estimation will be based on';
    } else if (!obj.CRF1 || !obj.bitrate1) {
      return 'Error: Please set CRF1 and bitrate1 values like they was in first/prev encode result';
    }

    let result;
    if (obj.CRF2) {
      result = obj.bitrate1 * Math.pow(Math.pow(10, (obj.CRF1 - obj.CRF2)), 0.1);
      result = Math.ceil(result);
      result = 'bitrate2 estimation is ' + result + ' kbps';
    } else {
      result = 10 * Math.log10(obj.bitrate1 / obj.bitrate2) + obj.CRF1;
      result = Math.ceil(result*10) / 10;
      result = 'CRF2 estimation is ' + result + ' points';
    }
    return result;
  }

  return calcNewCRForBitrate(obj);
}());

Comments (2)

  1. LiveM

    Hi! That's me who sent this script. Sorry for Anonymous account usage.

    Please combine this topic with it's description in https://bitbucket.org/multicoreware/x265/issues/338/crf-diffs-relatively-bit-rate-diffs

    I want to correct the script in aspect of working area.

    KG7x assemblies author shares 8,10,12bit builds on x265.ru/en/builds/. I do not know exactly that is it (--output-depth defaults only or whole encoder's pipeline is has the same color-channel depth or pipeline always has high bit depth) but the predictor script works great for x265 10bit builds. I use Visual C++ compiled builds (it gives about 1% performance increase for me among other compilers running on Intel G1610 CPU and Win10 v1607).

    Usual settings I used it with different CRF (22.5...27 for 1080p@25 and 720p@30 content): & 'c:\Program Files (x86)\AviSynth\additional\avs4x265.exe' c:\desktop\pph.avs --x265-binary 'c:\Program Files (x86)\AviSynth\additional\x265_64-10bit[vc12].exe' -o "c:\desktop\pph_138.hevc" --preset veryslow --crf 24 --crf-max 51 --crf-min 0 --vbv-maxrate 100000 --vbv-bufsize 2000000 --vbv-init 0.9 --qcomp 0.5 --qpstep 100 --rd 4 --ref 6 --bframes 16 --weightb --b-intra --max-merge 5 --subme 7 --tu-intra-depth 4 --tu-inter-depth 4 --limit-tu 0 --limit-refs 0 --no-limit-modes --rskip --no-amp --rc-lookahead 250 --pools '2' --wpp --no-pme --no-pmode --frame-threads 1 --lookahead-slices 0 --ssim --psnr --log-level 4

    I want to share this info with all, so please add it into your docs if you decide if it is correct in first approximation. I used it in 8-10 cases and approximation was always very close to results.

  2. LiveM

    extended to variable bit depths functionality:

    (function () {
      // ********************************
      //  x265 10bit bitrate or CRF predictor based on first encode.
      //  Looks like it works for x264 10 bit encode (tested on single instance only).
      //  Delivers approximate estimate.
      //
      //  Version 0.1.1.20170511
      //  RuTracker.org, LiveM
      //
      //  This script powered by maths below:
      //    For 10 bit encode: to change bit rate in 2 times we must change CRF by 3 points. Verified by own experience.
      //    !Perhaps! for 8 bit encode (!untested!): to change bit rate in 2 times we must change CRF by 6 points.
      //    !Perhaps! for 12 bit encode (!untested!): to change bit rate in 2 times we must change CRF by 1.5 points.
      //    !Perhaps! the CRF point where bit rates are the same for 8,10,12 bit encodes is about CRF=28 (!untested!).
      // ********************************
    
      let obj = {
    
        // first/previos encode. This is calcutation basis
        CRF1: 23.2,
        bitrate1: 3550, //in kbps
    
        // set one property to null to be estimated and another one the a numeric value you want
        CRF2: null,
        bitrate2: 3000, //in kbps
      },
    
      // set encoder's bit depth. Experimental untested feature.
      colorBitDepthOfEncoder = 10; //in bits. 10 bits value verified as making good predictions. 8 and 12 bits are experimental untested values.
    
      // ============================================================================================
      // script core
      function calcNewCRForBitrate(obj) {
        if ((obj.CRF2 && obj.bitrate2) || (!obj.CRF2 && !obj.bitrate2)) {
          return 'Error: Please set one unknown parameter to null value and another one to a number which the estimation will be based on';
        } else if (!obj.CRF1 || !obj.bitrate1) {
          return 'Error: Please set CRF1 and bitrate1 values like they was in first/prev encode result';
        }
        if (colorBitDepthOfEncoder !== 8 && colorBitDepthOfEncoder !== 10 && colorBitDepthOfEncoder !== 12) {
          return 'Error: Please set colorBitDepthOfEncoder to values either 8, 10 or 12';
        }
    
        let result,
          // script's core variables based on encoder bit depths
          CRFBitsBasedCoef = 5 * Math.pow(2, (6 - (colorBitDepthOfEncoder / 2))), // 8b -> 20, 10b -> 10, 12b -> 5
          BitRateBitsBasedCoef = 0.05 * Math.pow(2, ((colorBitDepthOfEncoder / 2) - 4)) ; // 8b -> 0.05, 10b -> 0.1, 12b -> 0.2
    
        if (obj.CRF2) {
          result = obj.bitrate1 * Math.pow(Math.pow(10, (obj.CRF1 - obj.CRF2)), BitRateBitsBasedCoef);
          result = Math.round(result);
          result = 'bitrate2 estimation is ' + result + ' kbps';
        } else {
          result = CRFBitsBasedCoef * Math.log10(obj.bitrate1 / obj.bitrate2) + obj.CRF1;
          result = Math.round(result*10) / 10;
          result = 'CRF2 estimation is ' + result + ' points';
        }
        return 'x265 ' + colorBitDepthOfEncoder + ' bits encoder: ' + result;
      }
    
      return calcNewCRForBitrate(obj);
    }());
    

    Copyright notes about site, author, version and other meta-content or script itself. I want to cut it out then it will be published your docs. It's your x265 encoder and my 'pull request' is extremely weak, so I want to leave it with no matter. Just review and publish the core content/main concept/script core itself in your docs section as you want. It's just to share an ability of wide use. Thanks for pay attention to this topic.

  3. Log in to comment