diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 8c14aa746e..d4a6fe0304 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -1322,7 +1322,7 @@ static int write_manifest(AVFormatContext *s, int final)
                     av_strlcat(codec_str, audio_codec_str, sizeof(codec_str));
                 }
                 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
-                ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
+                ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate, 0,
                                          playlist_file, agroup,
                                          codec_str, NULL, NULL);
             }
@@ -1348,7 +1348,7 @@ static int write_manifest(AVFormatContext *s, int final)
                     continue;
                 av_strlcpy(codec_str, os->codec_str, sizeof(codec_str));
                 get_hls_playlist_name(playlist_file, sizeof(playlist_file), NULL, i);
-                ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate,
+                ff_hls_write_stream_info(st, c->m3u8_out, stream_bitrate, 0,
                                          playlist_file, NULL,
                                          codec_str, NULL, NULL);
             }
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index 3ca99abdbb..26722c9b32 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -150,6 +150,11 @@ typedef struct VariantStream {
     int discontinuity;
     int reference_stream_index;
 
+    int64_t total_size;
+    double total_duration;
+    int64_t avg_bitrate;
+    int64_t max_bitrate;
+
     HLSSegment *segments;
     HLSSegment *last_segment;
     HLSSegment *old_segments;
@@ -1108,6 +1113,16 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls,
     if (!en)
         return AVERROR(ENOMEM);
 
+    vs->total_size += size;
+    vs->total_duration += duration;
+    if (duration > 0) {
+        int cur_bitrate = (int)(8 * size / duration);
+        if (cur_bitrate > vs->max_bitrate)
+            vs->max_bitrate = cur_bitrate;
+    }
+    if (vs->total_duration > 0)
+        vs->avg_bitrate = (int)(8 * vs->total_size / vs->total_duration);
+
     en->var_stream_idx = vs->var_stream_idx;
     ret = sls_flags_filename_process(s, hls, vs, en, duration, pos, size);
     if (ret < 0) {
@@ -1362,14 +1377,15 @@ static int64_t get_stream_bit_rate(AVStream *stream)
 }
 
 static int create_master_playlist(AVFormatContext *s,
-                                  VariantStream * const input_vs)
+                                  VariantStream * const input_vs,
+                                  int final)
 {
     HLSContext *hls = s->priv_data;
     VariantStream *vs, *temp_vs;
     AVStream *vid_st, *aud_st;
     AVDictionary *options = NULL;
     unsigned int i, j;
-    int ret, bandwidth;
+    int ret, bandwidth, avg_bandwidth;
     const char *m3u8_rel_name = NULL;
     const char *vtt_m3u8_rel_name = NULL;
     const char *ccgroup;
@@ -1389,8 +1405,8 @@ static int create_master_playlist(AVFormatContext *s,
                 return 0;
     } else {
          /* Keep publishing the master playlist at the configured rate */
-        if (&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
-            input_vs->number % hls->master_publish_rate)
+        if ((&hls->var_streams[0] != input_vs || !hls->master_publish_rate ||
+            input_vs->number % hls->master_publish_rate) && !final)
             return 0;
     }
 
@@ -1480,12 +1496,17 @@ static int create_master_playlist(AVFormatContext *s,
             }
         }
 
-        bandwidth = 0;
-        if (vid_st)
-            bandwidth += get_stream_bit_rate(vid_st);
-        if (aud_st)
-            bandwidth += get_stream_bit_rate(aud_st);
-        bandwidth += bandwidth / 10;
+        if (final) {
+            bandwidth = vs->max_bitrate;
+            avg_bandwidth = vs->avg_bitrate;
+        } else {
+            bandwidth = 0;
+            if (vid_st)
+                bandwidth += get_stream_bit_rate(vid_st);
+            if (aud_st)
+                bandwidth += get_stream_bit_rate(aud_st);
+            bandwidth += bandwidth / 10;
+        }
 
         ccgroup = NULL;
         if (vid_st && vs->ccgroup) {
@@ -1514,11 +1535,11 @@ static int create_master_playlist(AVFormatContext *s,
         }
 
         if (!hls->has_default_key || !hls->has_video_m3u8) {
-            ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
+            ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
                     aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
         } else {
             if (vid_st) {
-                ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, m3u8_rel_name,
+                ff_hls_write_stream_info(vid_st, hls->m3u8_out, bandwidth, avg_bandwidth, m3u8_rel_name,
                                          aud_st ? vs->agroup : NULL, vs->codec_attr, ccgroup, sgroup);
             }
         }
@@ -1671,7 +1692,7 @@ fail:
             ff_rename(temp_vtt_filename, vs->vtt_m3u8_name, s);
     }
     if (ret >= 0 && hls->master_pl_name)
-        if (create_master_playlist(s, vs) < 0)
+        if (create_master_playlist(s, vs, last) < 0)
             av_log(s, AV_LOG_WARNING, "Master playlist creation failed\n");
 
     return ret;
diff --git a/libavformat/hlsplaylist.c b/libavformat/hlsplaylist.c
index 4f35d0388f..f8a6977702 100644
--- a/libavformat/hlsplaylist.c
+++ b/libavformat/hlsplaylist.c
@@ -71,6 +71,7 @@ void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup,
 }
 
 void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth,
+                              int avg_bandwidth,
                               const char *filename, const char *agroup,
                               const char *codecs, const char *ccgroup,
                               const char *sgroup)
@@ -85,6 +86,8 @@ void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth,
     }
 
     avio_printf(out, "#EXT-X-STREAM-INF:BANDWIDTH=%d", bandwidth);
+    if (avg_bandwidth)
+        avio_printf(out, ",AVERAGE-BANDWIDTH=%d", avg_bandwidth);
     if (st && st->codecpar->width > 0 && st->codecpar->height > 0)
         avio_printf(out, ",RESOLUTION=%dx%d", st->codecpar->width,
                 st->codecpar->height);
diff --git a/libavformat/hlsplaylist.h b/libavformat/hlsplaylist.h
index c2744c227c..d7aa44d8dc 100644
--- a/libavformat/hlsplaylist.h
+++ b/libavformat/hlsplaylist.h
@@ -43,6 +43,7 @@ void ff_hls_write_subtitle_rendition(AVIOContext *out, const char *sgroup,
                                      const char *filename, const char *language,
                                      int name_id, int is_default);
 void ff_hls_write_stream_info(AVStream *st, AVIOContext *out, int bandwidth,
+                              int avg_bandwidth,
                               const char *filename, const char *agroup,
                               const char *codecs, const char *ccgroup,
                               const char *sgroup);
