[FFmpeg-user] HLS segment duration for multiple framerate encoding
Yisael Lowenstein
yisrael at catchmedia.com
Thu Jul 30 16:44:24 CEST 2015
I am trying to encode a video to HLS in multiple bitrates (and,
therefore, according to apple's recommendations, multiple frame rates).
I am doing this on video files (not live streams).
I can get one HLS working fine when I have a single variant, or multiple
variants of the same framerate. But when I have variants of different
framerates, I can't get the segment durations to line up.
For example, here are the first few lines of the m3u8 file of the same
video encoded a 15 fps and 30 fps.Note the durations of the first
segments have _different_lengths_. Also the TARGETDURATION is different.
#EXT-X-TARGETDURATION:10
#EXTINF:9.023222,
640_0.ts
#EXT-X-TARGETDURATION:9
#EXTINF:9.000000,
960_0.ts
My objective is to make a multi-bitrate (and multi-framerate) stream
that will pass apple's mediastreamvalidator test. I have spent a few
days scouring all the forums, tutorials, mailing lists, messageboards
etc...and I still can't get the streams to have segments of matching
durations when I use a different framerate...and without that, it won't
pass the test.
I have tried different segment options (segment vs. hls), different
keyframes options (-g / -force_key_frames), ffmpeg 2 pass methods, as
well as just using ffmpeg for transcoding and segmenting with apple's
segmenter. Even the apple segmentor is ends up segmenting the files so
the audio cuts off in the middle of each segment...
I'm sure this is something that can be done and is done regularly - can
anyone please enlighten me? (for anyone else reading this later on,
considder this an interesting summary of ways to use ffmpeg to create an
HLS stream.)
So, what am I doing wrong and how do I do it right?
Also, can anyone explain what the differences are between -g /
-force_key_framesand between hls / segment - and which one is
preferable to use?
====================================================================
ffmpeg version 2.7.1-static http://johnvansickle.com/ffmpeg/ Copyright
(c) 2000-2015 the FFmpeg developers
built with gcc 4.9.2 (Debian 4.9.2-21)
configuration: --enable-gpl --enable-version3 --disable-shared
--disable-debug --enable-runtime-cpudetect --enable-libmp3lame
--enable-libx264 --enable-libx265 --enable-libwebp --enable-libspeex
--enable-libvorbis --enable-libvpx --enable-libfreetype
--enable-fontconfig --enable-libxvid --enable-libopencore-amrnb
--enable-libopencore-amrwb --enable-libtheora --enable-libvo-aacenc
--enable-libvo-amrwbenc --enable-gray --enable-libopenjpeg
--enable-libopus --enable-libass --enable-gnutls --enable-libvidstab
--enable-libsoxr --cc=gcc-4.9
libavutil 54. 27.100 / 54. 27.100
libavcodec 56. 41.100 / 56. 41.100
libavformat 56. 36.100 / 56. 36.100
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 16.101 / 5. 16.101
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.100 / 1. 2.100
libpostproc 53. 3.100 / 53. 3.100
SOURCE: http://www.caminandes.com/download/01_llama_drama_1080p.zip
(from open movie project - note it is 24 fps - maybe that is the problem?)
Resolution: 1920x1080
FrameRate: 24
Profile: h264 High
TARGET: HLS
VARIANT 1:
Resolution: 480x270
FrameRate: 15
Video Bitrate: 400
Audio Bitrate: 64
Keyframe: 45 frames (3 seconds)
Profile: h264 Baseline, 3.0
Segment Size: 9 seconds
VARIANT 2:
Resolution: 640x360
FrameRate: 30 (yes, I am increasing the bitrate - but trying it
with 24 didn't help either)
Video Bitrate: 1200
Audio Bitrate: 96
Keyframe: 90 frames (3 seconds)
Profile: h264 Baseline, 3.1
Segment Size: 9 seconds
VARIANT 3:
Resolution: 960x540
FrameRate: 30
Video Bitrate: 1600
Audio Bitrate: 128
Keyframe: 90 frames (3 seconds)
Profile: h264 Main, 3.1
Segment Size: 9 seconds
Here is a summary of the methods I have tried and some of their
outputs: (I am aware that libfdk_aac is a better codec, but my version
currently doesn't have that compiled in)
0) hls commands, -force_key_frames
----------------------------------
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 15
-profile:v baseline -level 3 -b:v 400k -maxrate 428.00k
-force_key_frames "expr:gte(t,n_forced*3)" -vf "scale=480:-1"
-hls_list_size 0 -hls_time 9 480_.m3u8
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v baseline -level 3.1 -b:v 1200k -maxrate 1284.00k
-force_key_frames "expr:gte(t,n_forced*3)" -vf "scale=640:-1"
-hls_list_size 0 -hls_time 9 640_.m3u8
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v main -level 3.1 -b:v 1568k -maxrate 1677.76k
-force_key_frames "expr:gte(t,n_forced*3)" -vf "scale=960:-1"
-hls_list_size 0 -hls_time 9 960_.m3u8
#EXT-X-TARGETDURATION:10
#EXTINF:9.023222,
480_0.ts
#EXT-X-TARGETDURATION:10
#EXTINF:9.023222,
640_0.ts
#EXT-X-TARGETDURATION:9
#EXTINF:9.000000,
960_0.ts
1) hls commands, -g
-------------------
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 15
-profile:v baseline -level 3 -b:v 400k -maxrate 428.00k -g 45 -vf
"scale=480:-1" -hls_list_size 0 -hls_time 9 480_.m3u8
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v baseline -level 3.1 -b:v 1200k -maxrate 1284.00k -g 90 -vf
"scale=640:-1" -hls_list_size 0 -hls_time 9 640_.m3u8
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v main -level 3.1 -b:v 1568k -maxrate 1677.76k -g 90 -vf
"scale=960:-1" -hls_list_size 0 -hls_time 9 960_.m3u8
#EXT-X-TARGETDURATION:12
#EXTINF:11.156556,
480_0.ts
#EXT-X-TARGETDURATION:12
#EXTINF:11.056556,
640_0.ts
#EXT-X-TARGETDURATION:12
#EXTINF:11.033333,
960_0.ts
2) segment commands, -g
-----------------------
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 15
-profile:v baseline -level 3 -b:v 400k -maxrate 428.00k -g 45 -vf
"scale=480:-1" -f segment -segment_list 480_.m3u8 -segment_time 9
-segment_list_type m3u8 -segment_list_flags -cache+live 480_%05d.ts
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v baseline -level 3.1 -b:v 1200k -maxrate 1284.00k -g 90 -vf
"scale=640:-1" -f segment -segment_list 640_.m3u8 -segment_time 9
-segment_list_type m3u8 640_%05d.ts
./ffmpeg -y -i ../infile.mp4 -pix_fmt yuv420p -vbsf h264_mp4toannexb
-flags -global_header -vcodec libx264 -strict -2 -acodec aac -r 30
-profile:v main -level 3.1 -b:v 1568k -maxrate 1677.76k -g 90 -vf
"scale=960:-1" -f segment -segment_list 960_.m3u8 -segment_time 9
-segment_list_type m3u8 960_%05d.ts
#EXT-X-TARGETDURATION:12
#EXTINF:11.156556,
480_00000.ts
#EXT-X-TARGETDURATION:12
#EXTINF:11.056556,
640_00000.ts
#EXT-X-TARGETDURATION:12
#EXTINF:11.100000,
960_00000.ts
3) muti-pass (couldn't get it to work - based on:
https://sonnati.wordpress.com/2012/07/02/ffmpeg-the-swiss-army-knife-of-internet-streaming-part-v/
)
-------------
#FIRST PASS
./ffmpeg -i ../infile.mp4 -pass 1 -an -vcodec libx264 -r 30 -b:v 1200k
-bufsize 1200k -keyint_min 60 -g 120 -s 640x360 -f mpegts -y /dev/null
#SECOND PASS
./ffmpeg -i ../infile.mp4 -pass 2 -an -vcodec libx264 -r 30 -b:v 1200k
-bufsize 1200k -keyint_min 60 -g 120 -s 640x360 640_.mp4
#SECOND PASS WITH DIFFERENT FRAME RATE (FAILS)
./ffmpeg -i ../infile.mp4 -pass 2 -an -vcodec libx264 -r 15 -b:v 400k
-bufsize 400k -keyint_min 30 -g 60 -s 480x270 480_.mp4
#Error while opening encoder for output stream #0:0 - maybe
incorrect parameters such as bit_rate, rate, width or height
More information about the ffmpeg-user
mailing list