Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*
- import re
- from collections import namedtuple
- ext_x_targetduration = '#EXT-X-TARGETDURATION'
- ext_x_media_sequence = '#EXT-X-MEDIA-SEQUENCE'
- ext_x_key = '#EXT-X-KEY'
- ext_x_stream_inf = '#EXT-X-STREAM-INF'
- ext_x_version = '#EXT-X-VERSION'
- ext_x_allow_cache = '#EXT-X-ALLOW-CACHE'
- ext_x_endlist = '#EXT-X-ENDLIST'
- extinf = '#EXTINF'
- ATTRIBUTELISTPATTERN = re.compile(r'''((?:[^,"']|"[^"]*"|'[^']*')+)''')
- def parse(content):
- data = {
- 'is_variant': False,
- 'is_endlist': False,
- 'playlists': [],
- 'segments': [],
- }
- state = {
- 'expect_segment': False,
- 'expect_playlist': False,
- }
- for line in string_to_lines(content):
- line = line.strip()
- if 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 line.startswith(ext_x_targetduration):
- _parse_simple_parameter(line, data, float)
- elif line.startswith(ext_x_media_sequence):
- _parse_simple_parameter(line, data, int)
- elif line.startswith(ext_x_version):
- _parse_simple_parameter(line, data)
- elif line.startswith(ext_x_allow_cache):
- _parse_simple_parameter(line, data)
- elif line.startswith(ext_x_key):
- _parse_key(line, data)
- elif line.startswith(extinf):
- _parse_extinf(line, data, state)
- state['expect_segment'] = True
- elif line.startswith(ext_x_stream_inf):
- state['expect_playlist'] = True
- _parse_stream_inf(line, data, state)
- elif line.startswith(ext_x_endlist):
- data['is_endlist'] = True
- return data
- def _parse_key(line, data):
- params = ATTRIBUTELISTPATTERN.split(line.replace(ext_x_key + ':', ''))[1::2]
- data['key'] = {}
- for param in params:
- name, value = param.split('=', 1)
- data['key'][normalize_attribute(name)] = remove_quotes(value)
- def _parse_extinf(line, data, state):
- duration, title = line.replace(extinf + ':', '').split(',')
- state['segment'] = {'duration': float(duration), 'title': remove_quotes(title)}
- def _parse_ts_chunk(line, data, state):
- segment = state.pop('segment')
- segment['uri'] = line
- data['segments'].append(segment)
- def _parse_stream_inf(line, data, state):
- params = ATTRIBUTELISTPATTERN.split(line.replace(ext_x_stream_inf + ':', ''))[1::2]
- stream_info = {}
- for param in params:
- name, value = param.split('=', 1)
- stream_info[normalize_attribute(name)] = value
- if 'codecs' in stream_info:
- stream_info['codecs'] = remove_quotes(stream_info['codecs'])
- data['is_variant'] = True
- state['stream_info'] = stream_info
- def _parse_variant_playlist(line, data, state):
- playlist = {'uri': line,
- 'stream_info': state.pop('stream_info')}
- data['playlists'].append(playlist)
- def _parse_simple_parameter(line, data, cast_to=str):
- param, value = line.split(':', 1)
- param = normalize_attribute(param.replace('#EXT-X-', ''))
- value = normalize_attribute(value)
- data[param] = cast_to(value)
- def string_to_lines(string):
- return string.strip().replace('\r\n', '\n').split('\n')
- def remove_quotes(string):
- quotes = ('"', "'")
- if string and string[0] in quotes and string[-1] in quotes:
- return string[1:-1]
- return string
- def normalize_attribute(attribute):
- return attribute.replace('-', '_').lower().strip()
- def is_url(uri):
- return re.match(r'https?://', uri) is not None
Add Comment
Please, Sign In to add comment