Python-Hls analyzer: Analyzer for HTTP Live Streams (HLS) content

HLS Analyzer

Tool for analyzing HTTP Live Streams (HLS) compatible with both VOD and Live content.

It analyzes TS segments of the stream and provide useful information about the content, pretty useful to catch encoding or playback quality issues:

  • HLS information. Type of the stream (live or vod), media sequence, type of encryption and number of segments.
  • Tracks information. Video and audio tracks information (codecs, profiles, resolution, sample rate, channels, etc)
  • Timing information (PTS and segment duration). Useful to check if bitrates and segments are properly aligned.
  • Frames information. Keyframe interval, frames sequence. Useful to check if every segment starts with a keyframe. Useful to ensure smooth bitrate switching.

Command line tool syntax

python hls-analyzer.py [-h] [-s SEGMENTS] [-l FRAME_INFO_LEN] Url

  • Url: Url of the stream to be analyzed

Optional arguments:

  • -s SEGMENTS Number of segments to be analyzed per playlist. By default, one segment per playlist is analyzed
  • -l FRAME_INFO_LEN Max length per track for frames information
  • -h, --help Show help message

Example of use

python hls-analyzer.py https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8

Output:

Master playlist. List of variants:
    Playlist: https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/prog_index.m3u8, bw: 232370
    Playlist: https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/prog_index.m3u8, bw: 649879


***** Analyzing variant (232370) *****

    ** Generic information **
    Version: 3
    Media sequence: 0
    Is Live: False
    Encrypted: False
    Number of segments: 181
    Downloading https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear1/fileSequence0.ts, Range: None

    ** Tracks and Media formats **
    Track #0 - Type: video/avc, Format: Video (H.264) - Profile: Main, Level: 64, Resolution: 400x300, Encoded aspect ratio: 0/1, Display aspect ratio: 1
    Track #1 - Type: audio/mp4a-latm, Format: Audio (AAC) - Sample Rate: 22050, Channels: 2

    ** Timing information **
    Segment declared duration: 9.97667
    Track #0 - Duration: 9.943333 s, First PTS: 10.0 s, Last PTS: 19.943333 s
    Track #1 - Duration: 9.473739 s, First PTS: 9.904222 s, Last PTS: 19.377961 s
    Duration difference (declared vs real): 0.502931 s (5.31%)

    ** Frames **
    Track #0 - KF: 0.067, Frames: I-I-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-B-B-P-P-
    Track #1 - KF: 0.046, Frames: I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-


***** Analyzing variant (649879) *****

    ** Generic information **
    Version: 3
    Media sequence: 0
    Is Live: False
    Encrypted: False
    Number of segments: 181
    Downloading https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/gear2/fileSequence0.ts, Range: None

    ** Tracks and Media formats **
    Track #0 - Type: video/avc, Format: Video (H.264) - Profile: Main, Level: 64, Resolution: 640x480, Encoded aspect ratio: 0/1, Display aspect ratio: 1
    Track #1 - Type: audio/mp4a-latm, Format: Audio (AAC) - Sample Rate: 22050, Channels: 2

    ** Timing information **
    Segment declared duration: 9.97667
    Track #0 - Duration: 9.943333 s, First PTS: 10.0 s, Last PTS: 19.943333 s
    Track #1 - Duration: 9.473739 s, First PTS: 9.904222 s, Last PTS: 19.377961 s
    Duration difference (declared vs real): 0.502931 s (5.31%)

    ** Frames **
    Track #0 - KF: 0.067, Frames: I-I-I-I-I-P-P-P-P-P-B-B-B-B-B-P-P-P-P-P-B-B-B-B-B-P-P-P-P-P-B-B-B-B-B-P-P-P-P-P-
    Track #1 - KF: 0.046, Frames: I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-I-

Third party libraries

This project uses m3u8 library created by Globo.com: https://github.com/globocom/m3u8

Comments

  • IndexError: bytearray index out of range intermittently
    IndexError: bytearray index out of range intermittently

    Feb 14, 2017

    To reproduce please run the following, we are seeing bytearray index out of range intermittently.

    python hls-analyzer.py "https://cp541868-vh.akamaihd.net/i/mtvnorigin/gsp.alias/mediabus/mtv.com/2017/01/31/10/32/54/299d114ee3854f93a52389da76944592/1556899/1ftyUd0NW7_HDTNW610A4_1556899_7122114_,384x216_278,512x288_498,640x360_1028,768x432_1528,960x540_2128,1280x720_3128,1920x1080_5128,.mp4.csmil/master.m3u8?hdnea=st%3D1486567247%7Eexp%3D1487172047%7Eacl%3D%2Fi%2Fmtvnorigin%2Fgsp.alias%2Fmediabus%2Fmtv.com%2F2017%2F01%2F31%2F10%2F32%2F54%2F299d114ee3854f93a52389da76944592%2F1556899%2F1ftyUd0NW7_HDTNW610A4_1556899_7122114_%2C384x216_278%2C512x288_498%2C640x360_1028%2C768x432_1528%2C960x540_2128%2C1280x720_3128%2C1920x1080_5128%2C.mp4.csmil%2F*%7Ehmac%3Df8d18581e1bfd5b46a86b3c8f42182939fad51876dc7486d223c893f1620bb4b&__a__=off&__b__=450&__viacc__=NONE" >out.txt
    Traceback (most recent call last):
      File "hls-analyzer.py", line 210, in <module>
        analyze_variant(m3u8.load(playlist.absolute_uri), playlist.stream_info.bandwidth)
      File "hls-analyzer.py", line 63, in analyze_variant
        analyze_segment(variant.segments[i], bw, variant.media_sequence + i)
      File "hls-analyzer.py", line 167, in analyze_segment
        ts_parser.prepare()
      File "/home/ubuntu/workspace/ts_segment.py", line 33, in prepare
        self._readHeader()
      File "/home/ubuntu/workspace/ts_segment.py", line 94, in _readHeader
        self._processTSPacket(packet)
      File "/home/ubuntu/workspace/ts_segment.py", line 120, in _processTSPacket
        self._parseProgramId(payload_unit_start_indicator, packetParser)
      File "/home/ubuntu/workspace/ts_segment.py", line 137, in _parseProgramId
        packetParser.readBits(12)
      File "/home/ubuntu/workspace/bitreader.py", line 43, in readBits
        return self.readBitsLong(n)
      File "/home/ubuntu/workspace/bitreader.py", line 53, in readBitsLong
        retVal |= (self.readUnsignedByte() << n)
      File "/home/ubuntu/workspace/bitreader.py", line 75, in readUnsignedByte
        value = ((self.data[self.byteOffset]) << self.bitOffset) | ((self.data[self.byteOffset + 1]) >> (8 - self.bitOffset))
    IndexError: bytearray index out of range
    
    Reply
  • SyntaxError: invalid syntax
    SyntaxError: invalid syntax

    Jul 28, 2017

    Hello When I try to analyse the m2u8 the error below arise:

    D:\kodi\hls-analyzer-master>python hls-analyzer.py -h http://hls.fearfulale.xyz/s/ch0003660/22a3687fa0f4048a2d8a671d5122b15c.m3u8 File "hls-analyzer.py", line 119 print "{0}".format(track.payloadReader.frames[j].type), ^ SyntaxError: invalid syntax

    Reply
  • Traceback during an analyzation run after successfully inspecting several segments
    Traceback during an analyzation run after successfully inspecting several segments

    Oct 17, 2018

    ***** Analyzing variant (1478083) *****
    
    	** Generic information **
    	Version: 3
    	Start Media sequence: 279
    	Is Live: True
    	Encrypted: False
    	Number of segments: 10
    	Playlist duration: 60.06
    
    	** Downloading https://redacted/playlist_768x432_1200k_00286.ts, Range: None **
    	** Tracks and Media formats **
    	Track #0 - Type: video/avc, Format: Video (H.264) - Profile: Main, Level: 64, Resolution: 768x432, Encoded aspect ratio: 1/1, Display aspect ratio: 16/9
    	Track #1 - Type: audio/mp4a-latm, Format: Audio (AAC) - Sample Rate: 48000, Channels: 2
    	Track #2 - Type: unknown, Format: Unknown
    	Track #3 - Type: application/id3, Format: ID3
    
    	** Timing information **
    	Segment declared duration: 6.006
    	Track #0 - Duration: 5.939267 s, First PTS: 1689.752733 s, Last PTS: 1695.692 s
    	Track #1 - Duration: 5.973332 s, First PTS: 1689.756066 s, Last PTS: 1695.729398 s
    	Track #2 - Duration: 0.0 s, First PTS: 0.0 s, Last PTS: 0.0 s
    	Track #3 - Duration: 0.0 s, First PTS: 0.0 s, Last PTS: 0.0 s
    	Duration difference (declared vs real): 0.066733s (1.12%)
    
    	** Frames **
    	Track #0 - Frames:  I P B B B P B B B P B B B P B B B P B B B P B B B P B B B P 	AA: 286, BB: 1478083
    
    		Good! Track starts with a keyframe
    		Keyframes count: 3
    		Key frame interval within track: 2.002 seconds
    
    	Track #1 - Frames:  I I I I I I I I I I I I I I I I I I I I I I I I I I I I I I
    	Track #2 - Frames:
    	Track #3 - Frames:
    
    
    Traceback (most recent call last):
      File "hls-analyzer.py", line 214, in <module>
        analyze_variants_frame_alignment()
      File "hls-analyzer.py", line 180, in analyze_variants_frame_alignment
        if vf.segmentsFirstFramePts[segment_index] != value:
    KeyError: 285
    
    Reply
  • Add support for non RFC playlist from TSDuck
    Add support for non RFC playlist from TSDuck

    Feb 12, 2019

    In RFC we can find that after tag EXT-X-STREAM-INF we need to use the format below:

    #EXT-X-STREAM-INF:<attribute-list>
    <URI>
    

    but TSDuck add a custom tag after #EXT-X-STREAM-INF e.g.:

    #EXTM3U
    #EXT-X-VERSION:3
    #EXT-X-TARGETDURATION:5
    #EXT-X-MEDIA-SEQUENCE:4453
    #EXT-X-PLAYLIST-TYPE:EVENT
    #EXTINF:5.035,
    #EXT-X-BITRATE:722
    stream004453.ts
    #EXTINF:5.035,
    #EXT-X-BITRATE:620
    stream004454.ts
    

    So hls-analyzer trying to download chunk from the wrong link. This small patch resolve the issue.

    Reply
  • number of IPB frames displayed is limited
    number of IPB frames displayed is limited

    Jan 28, 2021

    When analyzing an HLS stream with mediainfo or DVBInspector, I a see a GOP with N=3 and M=50, but hls-analyzer seems limiting display of I P B at frame number 48, we cannot see end of sequence. Can you please help ?

    Reply
  • script incorrectly reports missing keyframes
    script incorrectly reports missing keyframes

    Jul 20, 2021

    script incorrectly reports absent keyframes:

    variant[894945].segment[2].track[0] keyframe_not_starting_track note this is not starting with a keyframe. This will cause not seamless bitrate switching

    whereas ffprobe thinks segment 2 starts with:

    [FRAME] media_type=video stream_index=0 key_frame=1

    Reply
  • Tidy up README formatting
    Tidy up README formatting

    Mar 16, 2018

    This cleans up the Markdown formatting, uses Markdown over HTML lists etc, and generally improves formatting.

    Reply
  • not an issue, but a question.
    not an issue, but a question.

    Jan 18, 2017

    Is there a legend about what means what in the hls analyzer report? For example, what does I - P - B mean in Frames section?

    question 
    Reply
  • bugfix: last keyframe interval was not being tracked properly
    bugfix: last keyframe interval was not being tracked properly

    Jan 6, 2017

    I noticed that the keyframe interval was always being reported as 0. Looks like it was a simple typo when tracking the pts of the last keyframe.

    Reply
  • Bug fix for key error. Added requirements and setup.py
    Bug fix for key error. Added requirements and setup.py

    Aug 19, 2016

                                                                                                                                                                                                           
    Reply
  • ValueError: zero length field name in format
    ValueError: zero length field name in format

    Apr 28, 2016

    [[email protected] hls-analyzer]# python hls-analyzer.py https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8 Master playlist. List of variants: Traceback (most recent call last): File "hls-analyzer.py", line 150, in print "\tPlaylist: {}, bw: {}".format(playlist.absolute_uri, playlist.stream_info.bandwidth) ValueError: zero length field name in format

    Python 2.6 on centos 6.7

    Reply
  • SyntaxError
    SyntaxError

    Dec 21, 2015

    Hi,

    Thanks for making this. It fits what I've looking for but I ran into an issue running it. Hopefully this is the best forum to report this issue.

    Command I used: python3 hls-analyzer.py http://playertest.longtailvideo.com/adaptive/bbbfull/bbbfull320x180.m3u8

    Result:

          File "hls-analyzer.py", line 35
            print "***** Analyzing variant ({}) *****".format(bw)
                                                     ^
        SyntaxError: invalid syntax
    

    I'm running Ubuntu 15.10.

    Thanks, Ian

    Reply