ffmpeg scenecut

min-keyint:
默认: auto (MIN(--keyint / 10, --fps))
设定IDR帧之间的最小间隔。
关于IDR帧的解释,参见 --keyint
keyint范围太小将导致IDR帧出现在"错误"的位置(如闪烁的场景(a strobing scene))。该选项限制每个IDR帧后必须经过多少帧才能出现下一个IDR帧。
min-keyint 的最大允许值为 --keyint/2+1
ffmpeg中使用keyint_min设置此项。
推荐值: 默认,或1倍帧率
 
no-scenecut:
完全禁止自动I帧选择算法(adaptive I-frame decision)

scenecut:
x264有一指标,用于衡量每一帧与前一帧的差异程度。
若该值小于scenecut,则检测到'场景切换'('scenecut')条件,
并放置一个I帧 (前提:该帧与上一个IDR帧的间隔小于min-keyint,否则就放置一个IDR帧)。
提高scenecut值将增加检测到的'场景切换'数量。
ffmpeg中使用-sc_threshold设置此项。
将scenecut设为0,相当于设定 no-scenecut


下面是我测试的一个例子,使用的是ffmpeg-1.2.4,如果需要用ffmpeg-0.10.4,则需要指定音频码率(-ab xxk)
    
1. 启用scenecut

1.1 对文件进行转码,其中参数-g设置为100,-sc_threshold设置为40: 

./ffmpeg -i h264_aac_20M.mp4 -f mp4 -b:v 200k -g 100 -sc_threshold 40 -y ./200k_no_scenecut.mp4

1.2 转码完成后,使用工具将输出文件的关键帧信息打印出来

 (其中key_frames为该视频的所有关键帧信息,frame为关键帧的帧号)
 ./key_frame_info ./200k_scenecut.mp4
     {
         "key_frames" :
         [
             {"frame":0, "ts":0.00},   
             {"frame":100, "ts":4.00}, 
             {"frame":200, "ts":8.00}, 
             {"frame":300, "ts":12.00},
             {"frame":338, "ts":13.52},
             {"frame":438, "ts":17.52},
             {"frame":538, "ts":21.52},
             {"frame":635, "ts":25.40},
             ...
             ...
         ]
     }

由上述信息可分析出: 
1.2.1 设置首帧为keyframe;
1.2.2 从首帧到第300帧之间,场景变化的指标都>sc_threshold,
所以根据-g=100来设置keyframe,则第100、200、300帧都被设置为keyframe;
1.2.3 转码程序侦测到第138帧与137帧之间的场景变化的指标< sc_threshold,
则会将138帧设置为keyframe,138之后的200帧之内场景变化的指标都>sc_threshold,
所以在148、158帧时又会根据-g=100的值来设置一个keyframe;
1.2.4 以后的关键帧设置都以此类推

2. 关闭scenecut
2.1 对文件进行转码: 
./ffmpeg -i h264_aac_20M.mp4 -f mp4 -b:v 200k -g 100 -sc_threshold 0 -y ./200k_no_scenecut.mp4

2.1 转码完成后,使用工具将输出文件的关键帧信息打印出来
./key_frame_info ./200k_no_scenecut.mp4
 (其中key_frames为该视频的所有关键帧信息,frame为关键帧的帧号)
    {
        "key_frames" :
        [ 
            {"frame":0, "ts":0.00},
            {"frame":100, "ts":4.00},
            {"frame":200, "ts":8.00},
            {"frame":300, "ts":12.00},
            {"frame":400, "ts":16.00},
            {"frame":500, "ts":20.00},
            {"frame":600, "ts":24.00},
            ...
            ...
        ]
    }
由上述信息可分析出: 当sc_threshold=0时,转码程序不会监测场景切换,直接根据-g=100来设置关键帧

3. 结论
当一个文件要在转码系统中输出多个码率的文件时,
可以将这个文件的一系列转码任务的参数-sc_threshold设置为0,同时设置任务的-g参数为同一个值,
这样转码输出的这多个码率的文件都会关闭场景切换监测的功能,同时会按照相同的-g参数来设置keyframe,
所以也算是实现了多码率输出时的gop对齐的功能。

4. 这样实现gop对齐会存在以下问题
4.1. 输出的文件的关键帧并没有按照场景切换,所以在seek的时候并不能seek到场景切换的地方
4.2. 快编系统原来定义的是根据视频的场景切换来进行分段,
但是如果场景切换监测关闭后,关键帧绝大部分都不会在场景切换的帧上,所以快编时分段就不会按场景划分了

所以如果确实要用到sc_threshold=0来实现gop对齐的功能,则需要考虑到快编系统的特点

你可能感兴趣的:(ffmpeg)