[FFmpeg-user] Fixed GOP encoding for HLS

Steven Liu lingjiujianke at gmail.com
Thu Dec 13 09:27:15 CET 2012


2012/12/12 Stefano Sabatini <stefasab at gmail.com>:
> On date Wednesday 2012-12-12 15:56:03 +1100, Andrew Sinclair wrote:
>> To wrap this one up and assist anyone else trying to do this here is how I
>> am achieving good results i.e. nicely aligned m3u8 files. Though there is
>> definitely some issue in regard to the lengths of the segments as reported
>> in the m3u8 files.
>>
>> In summary best thing I have found so far is to drop the scenecut frame
>> hints i.e. -g and -keyint_min and only add the -force_key_frames
>>
>
>> Apologies for the format of the output below but I have had to wrap this
>> all up in a series of Python scripts where I am also using ffprobe to check
>> that I have keyframes exactly where I want them.
>>
>> Encode cmd: ffmpeg -y -i /home/parallels/Videos/131375031.mp4 -pix_fmt
>> yuv420p -vcodec libx264 -r 24.0     -profile:v baseline -b:v 500k -maxrate
>> 500k  -force_key_frames
>
>> 0:00:06,0:00:12,0:00:18,0:00:24,0:00:30,0:00:36,0:00:42,0:00:48,0:00:54,0:01:00,0:01:06,0:01:12,0:01:18,0:01:24,0:01:30,0:01:36,0:01:42,0:01:48,0:01:54,0:02:00,0:02:06,0:02:12,0:02:18,0:02:24,0:02:30,0:02:36,0:02:42,0:02:48,0:02:54,0:03:00,0:03:06,0:03:12,0:03:18,0:03:24,0:03:30,0:03:36,0:03:42,0:03:48,0:03:54,0:04:00,0:04:06,0:04:12,0:04:18,0:04:24,0:04:30,0:04:36,0:04:42,0:04:48,0:04:54,0:05:00,0:05:06,0:05:12,0:05:18,0:05:24,0:05:30,0:05:36,0:05:42
>
> I think you can write the number of seconds, like 6,12,18,...
>
> Also maybe we should support reading from a file, or an expression of
> the type force_key_frames_expr gt(n*6-delta)*lt(n*6-delta)
>
>>      -s 640x360
> [...]
>> ffprobe -show_frames
>> /home/parallels/encodes/hls/131375031/131375031_500_640x360.ts
>>
>> ##### This is my parsed output showing that I have I frames exactly where I
>> want them ####
>> Found I frame as expected at 144.0
>> Found I frame as expected at 288.0
>> Found I frame as expected at 432.0
> [...]
>
> These doesn't match with the specified times (or are they frames
> numbers?).
>
> [...]
>> #### This is the full list of I Frames generated which shows additional
>> frames likely generated on scenecut so maintains maximum efficiency/quality
>> trade off
>>
>> 0,3,83,110,144,185,245,288,299,355,432,446,522,562,576,603,652,712,720,827,864,869,922,954,1008,1029,1090,1123,1139,1152,1177,1210,1238,1275,1296,1301,1331,1373,1398,1435,1440,1460,1479,1514,1584,1614,1633,1664,1695,1710,1727,1728,1746,1768,1797,1814,1835,1872,1998,2014,2016,2033,2042,2077,2132,2148,2160,2164,2204,2225,2252,2271,2282,2304,2319,2376,2399,2431,2448,2512,2513,2514,2535,2555,2575,2592,2613,2686,2736,2779,2880,2903,3024,3034,3064,3168,3194,3237,3266,3279,3291,3312,3323,3358,3442,3450,3456,3489,3578,3600,3604,3634,3682,3744,3888,3930,3975,4024,4032,4092,4131,4176,4194,4253,4265,4303,4320,4367,4397,4434,4464,4483,4512,4551,4608,4624,4689,4752,4803,4840,4896,4945,5007,5040,5066,5102,5141,5170,5184,5196,5211,5223,5237,5246,5266,5297,5318,5328,5373,5388,5413,5441,5457,5472,5490,5564,5616,5647,5694,5704,5742,5760,5899,5904,5936,5974,6048,6052,6070,6092,6119,6132,6155,6166,6180,6192,6206,6226,6239,6269,6291,6317,6332,6336,6340,6351,6366,6376,6384,6397,6406,6415,6426,64
>  33
>>  ,6456,6480,6528,6553,6577,6590,6602,6611,6619,6624,6628,6639,6649,6654,6669,6704,6751,6768,6816,6832,6855,6903,6912,6916,6937,6945,7008,7056,7200,7344,7488,7632,7776,7920,8064,8208,
> [...]
>> Segmenting file: ffmpeg -y -i
>> /home/parallels/encodes/hls/131375031/131375031_500_640x360.ts -codec copy
>> -map 0 -f segment -segment_list
>> /home/parallels/encodes/hls/131375031/index_500.m3u8 -segment_time 6
>>  -segment_list_type m3u8 131375031_500_640x360_%03d.ts
>> ('', "ffmpeg version N-45739-g04bf2e7 Copyright (c) 2000-2012 the FFmpeg
>> developers\n  built on Oct 20 2012 13:34:12 with gcc 4.6 (Ubuntu/Linaro
>> 4.6.3-1ubuntu5)\n  configuration: --enable-gpl --enable-libfaac
>> --enable-libfdk-aac --enable-libmp3lame --enable-libopencore-amrnb
>> --enable-libopencore-amrwb --enable-librtmp --enable-libtheora
>> --enable-libvorbis --enable-libvpx --enable-x11grab --enable-libx264
>> --enable-nonfree --enable-version3\n  libavutil      51. 76.100 / 51.
>> 76.100\n  libavcodec     54. 67.100 / 54. 67.100\n  libavformat    54.
>> 33.100 / 54. 33.100\n  libavdevice    54.  3.100 / 54.  3.100\n
>>  libavfilter     3. 19.103 /  3. 19.103\n  libswscale      2.  1.101 /  2.
>>  1.101\n  libswresample   0. 16.100 /  0. 16.100\n  libpostproc    52.
>>  1.100 / 52.  1.100\n[mpegts @ 0x302f260] max_analyze_duration 5000000
>> reached at 5015467\nInput #0, mpegts, from
>> '/home/parallels/encodes/hls/131375031/131375031_500_640x360.ts':\n
>>  Duration: 00:05:45.34, start: 1.389089, bitrate: 658 kb/s\n  Program 1 \n
>>    Metadata:\n      service_name    : Service01\n      service_provider:
>> FFmpeg\n    Stream #0:0[0x100]: Video: h264 (Constrained Baseline)
>> ([27][0][0][0] / 0x001B), yuv420p, 640x360 [SAR 1:1 DAR 16:9], 24 fps, 24
>> tbr, 90k tbn, 48 tbc\n    Stream #0:1[0x101](und): Audio: mp2 ([3][0][0][0]
>> / 0x0003), 44100 Hz, stereo, s16, 128 kb/s\nOutput #0, segment, to
>> '131375031_500_640x360_%03d.ts':\n  Metadata:\n    encoder         :
>> Lavf54.33.100\n    Stream #0:0: Video: h264 ([27][0][0][0] / 0x001B),
>> yuv420p, 640x360 [SAR 1:1 DAR 16:9], q=2-31, 24 fps, 90k tbn, 24 tbc\n
>>  Stream #0:1(und): Audio: mp2 ([3][0][0][0] / 0x0003), 44100 Hz, stereo,
>> 128 kb/s\nStream mapping:\n  Stream #0:0 -> #0:0 (copy)\n  Stream #0:1 ->
>> #0:1 (copy)\nPress [q] to stop, [?] for help\nframe= 8289 fps=0.0 q=-1.0
>> Lsize=       0kB time=00:05:45.41 bitrate=   0.0kbits/s
>>  \r\nvideo:19380kB audio:5397kB subtitle:0 global headers:0kB muxing
>> overhead -100.000000%\n")
>> Finish UTC time: 1355287042.41
>>
>> Segments then generate nicely aligned m3u8 however there is still something
>> a little odd with the rounding on the fragment sizes which don't appear to
>> line up with the actual fragment sizes.
>>
>> #EXTM3U
>> #EXT-X-VERSION:3
>> #EXT-X-MEDIA-SEQUENCE:0
>> #EXT-X-ALLOWCACHE:1
>> #EXTINF:6.034289,
>> 131375031_3500_1280x720_000.ts
>> #EXTINF:6.005422,
>> 131375031_3500_1280x720_001.ts
>> #EXTINF:6.013578,
>> 131375031_3500_1280x720_002.ts
>> #EXTINF:6.021744,
>> 131375031_3500_1280x720_003.ts
>> #EXTINF:6.003789,
>> 131375031_3500_1280x720_004.ts
>> #EXTINF:6.011944,
>> 131375031_3500_1280x720_005.ts
>> #EXTINF:6.020111,
>> 131375031_3500_1280x720_006.ts
>> #EXTINF:6.002156,
>> 131375031_3500_1280x720_007.ts
>> #EXTINF:6.010322,
>> 131375031_3500_1280x720_008.ts
>> #EXTINF:6.018478,
>> 131375031_3500_1280x720_009.ts
>> #EXTINF:6.000522,
>> 131375031_3500_1280x720_010.ts
>> #EXTINF:6.008689,
>> 131375031_3500_1280x720_011.ts
>> #EXTINF:6.016844,
>> 131375031_3500_1280x720_012.ts
>> #EXTINF:6.025011,
>> 131375031_3500_1280x720_013.ts
>> #EXTINF:6.007056,
>> 131375031_3500_1280x720_014.ts
>> #EXTINF:6.015211,
>> 131375031_3500_1280x720_015.ts
>> #EXTINF:6.023378,
>> 131375031_3500_1280x720_016.ts
>> #EXTINF:6.005422,
>> 131375031_3500_1280x720_017.ts
>> #EXTINF:6.013578,
>> 131375031_3500_1280x720_018.ts
>> #EXTINF:6.021744,
>> 131375031_3500_1280x720_019.ts
>> #EXTINF:6.003789,
>> 131375031_3500_1280x720_020.ts
>> #EXTINF:6.011944,
>> 131375031_3500_1280x720_021.ts
>> #EXTINF:6.020111,
>> 131375031_3500_1280x720_022.ts
>> #EXTINF:6.002156,
>> 131375031_3500_1280x720_023.ts
>> #EXTINF:6.010322,
>> 131375031_3500_1280x720_024.ts
>> #EXTINF:6.018478,
>> 131375031_3500_1280x720_025.ts
>> #EXTINF:6.000522,
>> 131375031_3500_1280x720_026.ts
>> #EXTINF:6.008689,
>> 131375031_3500_1280x720_027.ts
>> #EXTINF:6.016844,
>> 131375031_3500_1280x720_028.ts
>> #EXTINF:6.025011,
>> 131375031_3500_1280x720_029.ts
>> #EXTINF:6.007056,
>> 131375031_3500_1280x720_030.ts
>> #EXTINF:6.015211,
>> 131375031_3500_1280x720_031.ts
>> #EXTINF:6.023378,
>> 131375031_3500_1280x720_032.ts
>> #EXTINF:6.005422,
>> 131375031_3500_1280x720_033.ts
>> #EXTINF:6.013578,
>> 131375031_3500_1280x720_034.ts
>> #EXTINF:6.021744,
>> 131375031_3500_1280x720_035.ts
>> #EXTINF:6.003789,
>> 131375031_3500_1280x720_036.ts
>> #EXTINF:6.011944,
>> 131375031_3500_1280x720_037.ts
>> #EXTINF:6.020111,
>> 131375031_3500_1280x720_038.ts
>> #EXTINF:6.002156,
>> 131375031_3500_1280x720_039.ts
>> #EXTINF:6.010322,
>> 131375031_3500_1280x720_040.ts
>> #EXTINF:6.018478,
>> 131375031_3500_1280x720_041.ts
>> #EXTINF:6.000522,
>> 131375031_3500_1280x720_042.ts
>> #EXTINF:6.008689,
>> 131375031_3500_1280x720_043.ts
>> #EXTINF:6.016844,
>> 131375031_3500_1280x720_044.ts
>> #EXTINF:6.025011,
>> 131375031_3500_1280x720_045.ts
>> #EXTINF:6.007056,
>> 131375031_3500_1280x720_046.ts
>> #EXTINF:6.015211,
>> 131375031_3500_1280x720_047.ts
>> #EXTINF:6.023378,
>> 131375031_3500_1280x720_048.ts
>> #EXTINF:6.005422,
>> 131375031_3500_1280x720_049.ts
>> #EXTINF:6.013578,
>> 131375031_3500_1280x720_050.ts
>> #EXTINF:6.021744,
>> 131375031_3500_1280x720_051.ts
>> #EXTINF:6.003789,
>> 131375031_3500_1280x720_052.ts
>> #EXTINF:6.011944,
>> 131375031_3500_1280x720_053.ts
>> #EXTINF:6.020111,
>> 131375031_3500_1280x720_054.ts
>> #EXTINF:6.002156,
>> 131375031_3500_1280x720_055.ts
>> #EXTINF:6.010322,
>> 131375031_3500_1280x720_056.ts
>> #EXTINF:3.406233,
>> 131375031_3500_1280x720_057.ts
>> #EXT-X-TARGETDURATION:7
>> #EXT-X-ENDLIST
>>
>> However if I check the actual fragments using ffprobe it reports a
>> different length to in the m3u8
>>
>> ffprobe 131375031_3500_1280x720_000.ts
>> ffprobe version N-45739-g04bf2e7 Copyright (c) 2007-2012 the FFmpeg
>> developers
>>   built on Oct 20 2012 13:34:12 with gcc 4.6 (Ubuntu/Linaro 4.6.3-1ubuntu5)
>>   configuration: --enable-gpl --enable-libfaac --enable-libfdk-aac
>> --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb
>> --enable-librtmp --enable-libtheora --enable-libvorbis --enable-libvpx
>> --enable-x11grab --enable-libx264 --enable-nonfree --enable-version3
>>   libavutil      51. 76.100 / 51. 76.100
>>   libavcodec     54. 67.100 / 54. 67.100
>>   libavformat    54. 33.100 / 54. 33.100
>>   libavdevice    54.  3.100 / 54.  3.100
>>   libavfilter     3. 19.103 /  3. 19.103
>>   libswscale      2.  1.101 /  2.  1.101
>>   libswresample   0. 16.100 /  0. 16.100
>>   libpostproc    52.  1.100 / 52.  1.100
>> [mpegts @ 0x17e6c20] max_analyze_duration 5000000 reached at 5015467
>> Input #0, mpegts, from '131375031_3500_1280x720_000.ts':
>>   Duration: 00:00:06.00, start: 0.000000, bitrate: 3038 kb/s
>
> This is possibly an approximation of the duration.
>
>>   Program 1
>>     Metadata:
>>       service_name    : Service01
>>       service_provider: FFmpeg
>>     Stream #0:0[0x100]: Video: h264 (Constrained Baseline) ([27][0][0][0] /
>> 0x001B), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 24 fps, 24 tbr, 90k tbn, 48
>> tbc
>>     Stream #0:1[0x101]: Audio: mp2 ([3][0][0][0] / 0x0003), 44100 Hz,
>> stereo, s16, 128 kb/s
>>
>
>> If anyone is still reading down here next step I will have a look at
>> segment.c where I believe this is getting done.
>
> What I did in a similar situation:
>
> you set -force_key_frames with the list of frames, note that it is not
> perfectly accurate because of approximations so the actual I-frames
> may be placed before or after the specified time (this because you
> can't predict the position of video frames in the stream).
>
> No need to mess with encoder GOP options, since -force_key_frames
> overrides it, unless you want to avoid intermediary I-frames in order
> to reduce bandwidth. B-frames should be avoided.
>
> Then you pass the same list to -segment_times, and specify a
> segment_time_delta which is good enough for you (it may depends on the
> input, for constant frame rate (1/frame_rate) * 1/2 should be safe).
>
> An option to pass a file containing a list of times read by both
> -force_key_frames and -segment_times may be good to simplify
> scripting.
yap, this is good sugestion. :)


More information about the ffmpeg-user mailing list