(content, strict=False, custom_tags_parser=None)
return data
Given a M3U8 playlist content returns a dictionary with all data found
Given a M3U8 playlist content returns a dictionary with all data found
Given a M3U8 playlist content returns a dictionary with all data found
def parse(content, strict=False, custom_tags_parser=None):
    '''
    Given a M3U8 playlist content returns a dictionary with all data found
    '''
    data = {
        'media_sequence': 0,
        'is_variant': False,
        'is_endlist': False,
        'is_i_frames_only': False,
        'is_independent_segments': False,
        'playlist_type': None,
        'playlists': [],
        'segments': [],
        'iframe_playlists': [],
        'media': [],
        'keys': [],
        'rendition_reports': [],
        'skip': {},
        'part_inf': {},
        'session_data': [],
        'session_keys': [],
    }

    state = {
        'expect_segment': False,
        'expect_playlist': False,
        'current_key': None,
        'current_segment_map': None,
    }

    lineno = 0
    for line in string_to_lines(content):
        lineno += 1
        line = line.strip()

        if line.startswith(protocol.ext_x_byterange):
            _parse_byterange(line, state)
            state['expect_segment'] = True

        if line.startswith(protocol.ext_x_bitrate):
            _parse_bitrate(line, state)
            
        elif line.startswith(protocol.ext_x_targetduration):
            _parse_simple_parameter(line, data, float)

        elif line.startswith(protocol.ext_x_media_sequence):
            _parse_simple_parameter(line, data, int)

        elif line.startswith(protocol.ext_x_discontinuity_sequence):
            _parse_simple_parameter(line, data, int)

        elif line.startswith(protocol.ext_x_program_date_time):
            _, program_date_time = _parse_simple_parameter_raw_value(line, cast_date_time)
            if not data.get('program_date_time'):
                data['program_date_time'] = program_date_time
            state['current_program_date_time'] = program_date_time
            state['program_date_time'] = program_date_time

        elif line.startswith(protocol.ext_x_discontinuity):
            state['discontinuity'] = True

        elif line.startswith(protocol.ext_x_cue_out_cont):
            _parse_cueout_cont(line, state)
            state['cue_out'] = True

        elif line.startswith(protocol.ext_x_cue_out):
            _parse_cueout(line, state, string_to_lines(content)[lineno - 2])
            state['cue_out_start'] = True
            state['cue_out'] = True

        elif line.startswith(protocol.ext_x_cue_in):
            state['cue_in'] = True

        elif line.startswith(protocol.ext_x_cue_span):
            state['cue_out'] = True

        elif line.startswith(protocol.ext_x_version):
            _parse_simple_parameter(line, data, int)

        elif line.startswith(protocol.ext_x_allow_cache):
            _parse_simple_parameter(line, data)

        elif line.startswith(protocol.ext_x_key):
            key = _parse_key(line)
            state['current_key'] = key
            if key not in data['keys']:
                data['keys'].append(key)

        elif line.startswith(protocol.extinf):
            _parse_extinf(line, data, state, lineno, strict)
            state['expect_segment'] = True

        elif line.startswith(protocol.ext_x_stream_inf):
            state['expect_playlist'] = True
            _parse_stream_inf(line, data, state)

        elif line.startswith(protocol.ext_x_i_frame_stream_inf):
            _parse_i_frame_stream_inf(line, data)

        elif line.startswith(protocol.ext_x_media):
            _parse_media(line, data, state)

        elif line.startswith(protocol.ext_x_playlist_type):
            _parse_simple_parameter(line, data)

        elif line.startswith(protocol.ext_i_frames_only):
            data['is_i_frames_only'] = True

        elif line.startswith(protocol.ext_is_independent_segments):
            data['is_independent_segments'] = True

        elif line.startswith(protocol.ext_x_endlist):
            data['is_endlist'] = True

        elif line.startswith(protocol.ext_x_map):
            quoted_parser = remove_quotes_parser('uri')
            segment_map_info = _parse_attribute_list(protocol.ext_x_map, line, quoted_parser)
            state['current_segment_map'] = segment_map_info
            # left for backward compatibility
            data['segment_map'] = segment_map_info

        elif line.startswith(protocol.ext_x_start):
            attribute_parser = {
                "time_offset": lambda x: float(x)
            }
            start_info = _parse_attribute_list(protocol.ext_x_start, line, attribute_parser)
            data['start'] = start_info

        elif line.startswith(protocol.ext_x_server_control):
            _parse_server_control(line, data, state)

        elif line.startswith(protocol.ext_x_part_inf):
            _parse_part_inf(line, data, state)

        elif line.startswith(protocol.ext_x_rendition_report):
            _parse_rendition_report(line, data, state)

        elif line.startswith(protocol.ext_x_part):
            _parse_part(line, data, state)

        elif line.startswith(protocol.ext_x_skip):
            _parse_skip(line, data, state)

        elif line.startswith(protocol.ext_x_session_data):
            _parse_session_data(line, data, state)

        elif line.startswith(protocol.ext_x_session_key):
            _parse_session_key(line, data, state)

        elif line.startswith(protocol.ext_x_preload_hint):
            _parse_preload_hint(line, data, state)

        elif line.startswith(protocol.ext_x_daterange):
            _parse_daterange(line, data, state)

        elif line.startswith(protocol.ext_x_gap):
            state['gap'] = True

        # Comments and whitespace
        elif line.startswith('#'):
            if callable(custom_tags_parser):
                custom_tags_parser(line, data, lineno)

        elif line.strip() == '':
            # blank lines are legal
            pass

        elif state['expect_segment']:
            _parse_ts_chunk(line, data, state)
            state['expect_segment'] = False

        elif state['expect_playlist']:
            _parse_variant_playlist(line, data, state)
            state['expect_playlist'] = False

        elif strict:
            raise ParseError(lineno, line)

    # there could be remaining partial segments
    if 'segment' in state:
        data['segments'].append(state.pop('segment'))

    return data
def parse ( content , strict = False , custom_tags_parser = None ) : data = { 'media_sequence' : 0 , 'is_variant' : False , 'is_endlist' : False , 'is_i_frames_only' : False , 'is_independent_segments' : False , 'playlist_type' : None , 'playlists' : [ ] , 'segments' : [ ] , 'iframe_playlists' : [ ] , 'media' : [ ] , 'keys' : [ ] , 'rendition_reports' : [ ] , 'skip' : { } , 'part_inf' : { } , 'session_data' : [ ] , 'session_keys' : [ ] , } state = { 'expect_segment' : False , 'expect_playlist' : False , 'current_key' : None , 'current_segment_map' : None , } lineno = 0 for line in string_to_lines ( content ) : lineno += 1 line = line . strip ( ) if line . startswith ( protocol . ext_x_byterange ) : _parse_byterange ( line , state ) state [ 'expect_segment' ] = True if line . startswith ( protocol . ext_x_bitrate ) : _parse_bitrate ( line , state ) elif line . startswith ( protocol . ext_x_targetduration ) : _parse_simple_parameter ( line , data , float ) elif line . startswith ( protocol . ext_x_media_sequence ) : _parse_simple_parameter ( line , data , int ) elif line . startswith ( protocol . ext_x_discontinuity_sequence ) : _parse_simple_parameter ( line , data , int ) elif line . startswith ( protocol . ext_x_program_date_time ) : _ , program_date_time = _parse_simple_parameter_raw_value ( line , cast_date_time ) if not data . get ( 'program_date_time' ) : data [ 'program_date_time' ] = program_date_time state [ 'current_program_date_time' ] = program_date_time state [ 'program_date_time' ] = program_date_time elif line . startswith ( protocol . ext_x_discontinuity ) : state [ 'discontinuity' ] = True elif line . startswith ( protocol . ext_x_cue_out_cont ) : _parse_cueout_cont ( line , state ) state [ 'cue_out' ] = True elif line . startswith ( protocol . ext_x_cue_out ) : _parse_cueout ( line , state , string_to_lines ( content ) [ lineno - 2 ] ) state [ 'cue_out_start' ] = True state [ 'cue_out' ] = True elif line . startswith ( protocol . ext_x_cue_in ) : state [ 'cue_in' ] = True elif line . startswith ( protocol . ext_x_cue_span ) : state [ 'cue_out' ] = True elif line . startswith ( protocol . ext_x_version ) : _parse_simple_parameter ( line , data , int ) elif line . startswith ( protocol . ext_x_allow_cache ) : _parse_simple_parameter ( line , data ) elif line . startswith ( protocol . ext_x_key ) : key = _parse_key ( line ) state [ 'current_key' ] = key if key not in data [ 'keys' ] : data [ 'keys' ] . append ( key ) elif line . startswith ( protocol . extinf ) : _parse_extinf ( line , data , state , lineno , strict ) state [ 'expect_segment' ] = True elif line . startswith ( protocol . ext_x_stream_inf ) : state [ 'expect_playlist' ] = True _parse_stream_inf ( line , data , state ) elif line . startswith ( protocol . ext_x_i_frame_stream_inf ) : _parse_i_frame_stream_inf ( line , data ) elif line . startswith ( protocol . ext_x_media ) : _parse_media ( line , data , state ) elif line . startswith ( protocol . ext_x_playlist_type ) : _parse_simple_parameter ( line , data ) elif line . startswith ( protocol . ext_i_frames_only ) : data [ 'is_i_frames_only' ] = True elif line . startswith ( protocol . ext_is_independent_segments ) : data [ 'is_independent_segments' ] = True elif line . startswith ( protocol . ext_x_endlist ) : data [ 'is_endlist' ] = True elif line . startswith ( protocol . ext_x_map ) : quoted_parser = remove_quotes_parser ( 'uri' ) segment_map_info = _parse_attribute_list ( protocol . ext_x_map , line , quoted_parser ) state [ 'current_segment_map' ] = segment_map_info # left for backward compatibility data [ 'segment_map' ] = segment_map_info elif line . startswith ( protocol . ext_x_start ) : attribute_parser = { "time_offset" : lambda x : float ( x ) } start_info = _parse_attribute_list ( protocol . ext_x_start , line , attribute_parser ) data [ 'start' ] = start_info elif line . startswith ( protocol . ext_x_server_control ) : _parse_server_control ( line , data , state ) elif line . startswith ( protocol . ext_x_part_inf ) : _parse_part_inf ( line , data , state ) elif line . startswith ( protocol . ext_x_rendition_report ) : _parse_rendition_report ( line , data , state ) elif line . startswith ( protocol . ext_x_part ) : _parse_part ( line , data , state ) elif line . startswith ( protocol . ext_x_skip ) : _parse_skip ( line , data , state ) elif line . startswith ( protocol . ext_x_session_data ) : _parse_session_data ( line , data , state ) elif line . startswith ( protocol . ext_x_session_key ) : _parse_session_key ( line , data , state ) elif line . startswith ( protocol . ext_x_preload_hint ) : _parse_preload_hint ( line , data , state ) elif line . startswith ( protocol . ext_x_daterange ) : _parse_daterange ( line , data , state ) elif line . startswith ( protocol . ext_x_gap ) : state [ 'gap' ] = True # Comments and whitespace elif line . startswith ( '#' ) : if callable ( custom_tags_parser ) : custom_tags_parser ( line , data , lineno ) elif line . strip ( ) == '' : # blank lines are legal pass elif state [ 'expect_segment' ] : _parse_ts_chunk ( line , data , state ) state [ 'expect_segment' ] = False elif state [ 'expect_playlist' ] : _parse_variant_playlist ( line , data , state ) state [ 'expect_playlist' ] = False elif strict : raise ParseError ( lineno , line ) # there could be remaining partial segments if 'segment' in state : data [ 'segments' ] . append ( state . pop ( 'segment' ) ) return data