Search code examples
ffmpegh.264video-processingvideo-encoding

Does a scencut feature of H.264 increases a file size?


When I use this command:

ffmpeg -i original.mp4 -codec:v:0 libx264  -b:v 650k -crf 21 -minrate:v 0k -maxrate:v 750k -bufsize:v 5000k -r 30 -preset slow -x264opts "no-scenecut" -vcodec libx264 -force_key_frames "expr:bitor(eq(t,0),gte(t,prev_forced_t+5))" -f mp4 test.mp4

I always get smaller file size than from this command (same command but without: -x264opts "no-scenecut"):

ffmpeg -i original.mp4 -codec:v:0 libx264  -b:v 650k -crf 21 -minrate:v 0k -maxrate:v 750k -bufsize:v 5000k -r 30 -preset slow -vcodec libx264 -force_key_frames "expr:bitor(eq(t,0),gte(t,prev_forced_t+5))" -f mp4 test.mp4

I thought that the scencut puts I frames only if it is more efficient to use I frame insted of P or B frame.
In what cases we need to use the scencut feature?


Solution

  • When a scenecut triggers it puts either an IDR if the distance is greater than min-keyint OR an I-frame otherwise.

    Here's some pseudo-code posted on the doom9.org forum (adding it here for future reference):

    encode current frame as (a really fast approximation of) a P-frame and an I-frame.
    
    if ((distance from previous keyframe) > keyint) then
        set IDR-frame
    else if (1 - (bit size of P-frame) / (bit size of I-frame) < (scenecut / 100) * (distance from previous keyframe) / keyint) then
        if ((distance from previous keyframe) >= minkeyint) then
            set IDR-frame
        else
            set I-frame
    else
        set P-frame
    
    encode frame for real.
    

    You should use scenecut when you don't need a fixed GOP / forced keyframes. If you're trying to encode for ABR delivery then you can alternatively use two-pass encoding and generate a stat file for the highest resolution on pass-1 and then reuse it on pass-2 for each rendition.