Opened 6 years ago
Last modified 16 months ago
#7403 reopened defect
HLS Master Playlist fails being generated correctly
Reported by: | barhom | Owned by: | |
---|---|---|---|
Priority: | minor | Component: | avformat |
Version: | git-master | Keywords: | hls |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | yes | |
Analyzed by developer: | no |
Description
Summary of the bug:
How to reproduce:
ffmpeg -i input.ts -c copy -f hls -master_pl_name master.m3u8 -var_stream_map "v:0,a:0" "vs_%v/playlist.m3u8"
input.ts is attached.
This has been tested on ffmpeg compiled on 2018-09-05.
What is wrong:
FFmpeg fails to read the bitrate of the input.ts and thus fails to write the master.m3u8
The code below is what controls this error.
if (!bandwidth) { av_log(NULL, AV_LOG_WARNING, "Bandwidth info not available, set audio and video bitrates\n"); return; }
My thoughts is that the proper way would not to return if bandwidth is not available but simply write the playlist without the bandwidth information since it was not available.
Attachments (1)
Change History (14)
by , 6 years ago
follow-ups: 3 4 comment:1 by , 6 years ago
comment:2 by , 6 years ago
A possible method of handling such cases is to manually pass the video bitrate and audio bitrate in the command line.
For example
ffmpeg -i input.ts -c copy -b:v 1000k -b:a 128k -f hls -master_pl_name master.m3u8 -var_stream_map "v:0,a:0" "vs_%v/playlist.m3u8"
The above command will create the master playlist.
comment:3 by , 6 years ago
Replying to j_karthic:
As per the HLS specification, bandwidth attribute is mandatory. So it would be in violation of the spec to create a master playlist without bandwidth information.
If so, should we not even copy the input to the output vs_0/playlist.m3u8?
Otherwise we are creating a working playlist.m3u8 but a non-working master.m3u8.
MPEG2 video inside HLS containers are also invalid according to the spec but they are still allowed.
comment:5 by , 6 years ago
Keywords: | hls added; hlsplaylist.c removed |
---|---|
Priority: | normal → minor |
Reproduced by developer: | set |
Version: | unspecified → git-master |
comment:6 by , 6 years ago
HLS clients can still playout the playlist.m3u8 directly, even without a master playlist.
Master playlist is primarily meant for choosing content between different playlists based on bandwidth. Hence bandwidth has been made mandatory attribute by the spec.
As far as I understand HLS spec doesn't impose any restriction on codec type inside the MPEG-TS container.
comment:7 by , 6 years ago
I am closing this since it does not seem like it is something that needs fixing.
comment:8 by , 6 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
follow-up: 10 comment:9 by , 6 years ago
Resolution: | invalid |
---|---|
Status: | closed → reopened |
There is definitely a bug, I don't know if it is the level of the console log or something else.
comment:10 by , 6 years ago
Replying to cehoyos:
There is definitely a bug, I don't know if it is the level of the console log or something else.
You mean the bug is that it cant read the bitrate? Or that it should continue generating the master playlist without the bitrate?
comment:12 by , 22 months ago
I can confirm this issue when trying to stream from hls. Example input: https://gist.github.com/knyttl/1049b5ac4ee192ce95e68e9d3cd8fa93
When you simple copy and output the input streams as:
ffmpeg -i 'input.m3u8' -map 0:0 -c:0 copy -map 0:1 -c:1 copy -map 0:2 -c:2 copy -map 0:3 -c:3 copy -f hls -hls_list_size 0 -hls_playlist_type vod -hls_segment_type mpegts -hls_segment_filename result/%v/%03d.ts -master_pl_name playlist.m3u8 -var_stream_map 'v:0 v:1 v:2 v:3' result/%v/chunk.m3u8
This will nicely generate the separate stream directories, but then this error will appear:
Bandwidth info not available, set audio and video bitrates.
The original stream contains these:
#EXT-X-STREAM-INF:BANDWIDTH=3212710,AVERAGE-BANDWIDTH=3212710
This can be easily fixed by manually setting the bitrate with -b:v, but that is not what I want to do if I just want to copy the input stream. Is there a way to force it to read the original bitrates?
comment:13 by , 16 months ago
It's definitely a bug. And here's why:
I'm working on a service that takes a video file as input and generates HLS streams in various resolutions as output (like YouTube does).
If the input file has no audio, running the following command:
ffmpeg -i input.mp4 -map 0:v:0 -map 0:v:0 -map 0:v:0 -map 0:v:0 -filter:v:0 scale=-2:360 -filter:v:1 scale=-2:480 -filter:v:2 scale=-2:720 -filter:v:3 scale=-2:1080 -f hls -hls_playlist_type vod -hls_flags independent_segments -master_pl_name master.m3u8 -hls_segment_filename stream_%v/chunk_%08d.ts -strftime_mkdir 1 -var_stream_map "v:0,name:360p v:1,name:480p v:2,name:720p v:3,name:1080p" stream_%v.m3u8
causes the following warning(s):
Bandwidth info not available, set audio and video bitrates Last message repeated 3 times
and produce the following broken HLS master playlist:
#EXTM3U #EXT-X-VERSION:6
This can be fixed by specifying the bitrate explicitly, e.g. -b:v:0 1000k -b:v:1 2000k -b:v:2 4000k -b:v:3 6000k
.
But I don't want to explicitly specify the video bitrate for each stream. I want to use ffmpeg's default values. By the way, I don't know the ffmpeg's default values for various resolutions. Moreover, to get a high-quality output video, I need to consider not only the resolution, but also the frame rate. E.g., a video with 60 fps needs a higher bitrate than a video with the same resolution but 30 fps. And the problem is that I don't know the frame rate of the input video that the user can upload.
The interesting thing is that there is another way to create an HLS streams using dash
muxer with -hls_playlist true
option:
ffmpeg -i input.mp4 -map 0:v:0 -map 0:v:0 -map 0:v:0 -map 0:v:0 -filter:v:0 scale=-2:360 -filter:v:1 scale=-2:480 -filter:v:2 scale=-2:720 -filter:v:3 scale=-2:1080 -use_template 1 -use_timeline 1 -adaptation_sets "id=0,streams=v" -f dash -hls_playlist true manifest.mpd
This also causes the following warning(s):
[dash @ 000001fe89d20cc0] No bit rate set for stream 0 [dash @ 000001fe89d20cc0] No bit rate set for stream 1 [dash @ 000001fe89d20cc0] No bit rate set for stream 2 [dash @ 000001fe89d20cc0] No bit rate set for stream 3
but produce the following correct master.m3u8
HLS master playlist (alongside manifest.mpd
DASH master playlist):
#EXTM3U #EXT-X-VERSION:7 #EXT-X-STREAM-INF:BANDWIDTH=987359,RESOLUTION=640x360,CODECS="avc1.64001f" media_0.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=1504372,RESOLUTION=854x480,CODECS="avc1.64001f" media_1.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2787800,RESOLUTION=1280x720,CODECS="avc1.640020" media_2.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=5181173,RESOLUTION=1920x1080,CODECS="avc1.64002a" media_3.m3u8
This means that ffmpeg actually has all the info about video bitrate it needs and that this is definitely a bug in hls
muxer that expects the user to specify the bitrate explicitly.
Moreover, if the hls
muxer is used, but the input video file has audio, running the following command:
ffmpeg -i input.mp4 -map 0:v:0 -map 0:v:0 -map 0:v:0 -map 0:v:0 -map 0:a:0 -filter:v:0 scale=-2:360 -filter:v:1 scale=-2:480 -filter:v:2 scale=-2:720 -filter:v:3 scale=-2:1080 -f hls -hls_playlist_type vod -hls_flags independent_segments -master_pl_name master.m3u8 -hls_segment_filename stream_%v/chunk_%08d.ts -strftime_mkdir 1 -var_stream_map "v:0,name:360p,agroup:audio v:1,name:480p,agroup:audio v:2,name:720p,agroup:audio v:3,name:1080p,agroup:audio a:0,name:audio,agroup:audio" stream_%v.m3u8
doesn't cause any warnings and produce the following master playlist:
#EXTM3U #EXT-X-VERSION:6 #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_audio",NAME="audio_4",DEFAULT=YES,URI="stream_audio.m3u8" #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=640x360,CODECS="avc1.64001f,mp4a.40.2",AUDIO="group_audio" stream_360p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=854x480,CODECS="avc1.64001f,mp4a.40.2",AUDIO="group_audio" stream_480p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1280x720,CODECS="avc1.640020,mp4a.40.2",AUDIO="group_audio" stream_720p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=140800,RESOLUTION=1920x1080,CODECS="avc1.64002a,mp4a.40.2",AUDIO="group_audio" stream_1080p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=140800,CODECS="mp4a.40.2",AUDIO="group_audio" stream_audio.m3u8
But all video streams have the same bandwidth as the audio stream that is obviously incorrect.
As per the HLS specification, bandwidth attribute is mandatory. So it would be in violation of the spec to create a master playlist without bandwidth information.