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)

input.ts (1.1 MB ) - added by barhom 6 years ago.

Download all attachments as: .zip

Change History (14)

by barhom, 6 years ago

Attachment: input.ts added

comment:1 by Karthick Jeyapal, 6 years ago

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.

comment:2 by Karthick Jeyapal, 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.

Last edited 6 years ago by Karthick Jeyapal (previous) (diff)

in reply to:  1 comment:3 by barhom, 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.

in reply to:  1 comment:4 by barhom, 6 years ago

double post, sorry

Last edited 6 years ago by barhom (previous) (diff)

comment:5 by Carl Eugen Hoyos, 6 years ago

Keywords: hls added; hlsplaylist.c removed
Priority: normalminor
Reproduced by developer: set
Version: unspecifiedgit-master

comment:6 by Karthick Jeyapal, 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.

Last edited 6 years ago by Karthick Jeyapal (previous) (diff)

comment:7 by barhom, 6 years ago

I am closing this since it does not seem like it is something that needs fixing.

comment:8 by barhom, 6 years ago

Resolution: invalid
Status: newclosed

comment:9 by Carl Eugen Hoyos, 6 years ago

Resolution: invalid
Status: closedreopened

There is definitely a bug, I don't know if it is the level of the console log or something else.

in reply to:  9 comment:10 by barhom, 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:11 by Carl Eugen Hoyos, 6 years ago

I don't know.

comment:12 by nnnytt, 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?

Last edited 22 months ago by nnnytt (previous) (diff)

comment:13 by alexey.rodionov, 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.

Note: See TracTickets for help on using tickets.