Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def __str__(self):
media_types = []
stream_inf = [str(self.stream_info)]
for media in self.media:
if media.type in media_types:
continue
else:
media_types += [media.type]
media_type = media.type.upper()
stream_inf.append('%s="%s"' % (media_type, media.group_id))
return '#EXT-X-STREAM-INF:' + ','.join(stream_inf) + '\n' + self.uri
class IFramePlaylist(BasePathMixin):
'''
IFramePlaylist object representing a link to a
variant M3U8 i-frame playlist with a specific bitrate.
Attributes:
`iframe_stream_info` is a named tuple containing the attributes:
`program_id`, `bandwidth`, `codecs` and `resolution` which
is a tuple (w, h) of integers
More info: http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.13
'''
def __init__(self, base_uri, uri, iframe_stream_info):
self.uri = uri
self.base_uri = base_uri
return "{tag}:{attributes}".format(tag=self.tag, attributes=",".join(output))
def __eq__(self, other):
if not other:
return False
return self.uri == other.uri and \
self.byterange == other.byterange and \
self.base_uri == other.base_uri
def __ne__(self, other):
return not self.__eq__(other)
class SessionKey(Key):
tag = ext_x_session_key
class Playlist(BasePathMixin):
'''
Playlist object representing a link to a variant M3U8 with a specific bitrate.
Attributes:
`stream_info` is a named tuple containing the attributes: `program_id`,
`bandwidth`, `average_bandwidth`, `resolution`, `codecs` and `resolution`
which is a a tuple (w, h) of integers
`media` is a list of related Media entries.
More info: http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.10
'''
def __init__(self, uri, stream_info, media, base_uri):
self.uri = uri
class Start(object):
def __init__(self, time_offset, precise=None):
self.time_offset = float(time_offset)
self.precise = precise
def __str__(self):
output = [
'TIME-OFFSET=' + str(self.time_offset)
]
if self.precise and self.precise in ['YES', 'NO']:
output.append('PRECISE=' + str(self.precise))
return ext_x_start + ':' + ','.join(output)
class RenditionReport(BasePathMixin):
def __init__(self, base_uri, uri, last_msn, last_part=None):
self.base_uri = base_uri
self.uri = uri
self.last_msn = last_msn
self.last_part = last_part
def dumps(self):
report = []
report.append('URI=' + quoted(self.uri))
report.append('LAST-MSN=' + number_to_string(self.last_msn))
if self.last_part is not None:
report.append('LAST-PART=' + number_to_string(
self.last_part))
return ('#EXT-X-RENDITION-REPORT:' + ','.join(report))
self._create_sub_directories(filename)
with open(filename, 'w') as fileobj:
fileobj.write(self.dumps())
def _create_sub_directories(self, filename):
basename = os.path.dirname(filename)
try:
if basename:
os.makedirs(basename)
except OSError as error:
if error.errno != errno.EEXIST:
raise
class Segment(BasePathMixin):
'''
A video segment from a M3U8 playlist
`uri`
a string with the segment uri
`title`
title attribute from EXTINF parameter
`program_date_time`
Returns the EXT-X-PROGRAM-DATE-TIME as a datetime. This field is only set
if EXT-X-PROGRAM-DATE-TIME exists for this segment
http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.5
`current_program_date_time`
Returns a datetime of this segment, either the value of `program_date_time`
return self.tag + ':' + ','.join(output)
def __eq__(self, other):
if not other:
return False
return self.method == other.method and \
self.uri == other.uri and \
self.iv == other.iv and \
self.base_uri == other.base_uri and \
self.keyformat == other.keyformat and \
self.keyformatversions == other.keyformatversions
def __ne__(self, other):
return not self.__eq__(other)
class InitializationSection(BasePathMixin):
'''
Used to obtain Media Initialization Section required to
parse the applicable Media Segments (EXT-X-MAP)
`uri`
is a string. ex:: "https://priv.example.com/key.php?r=52"
`byterange`
value of BYTERANGE attribute
`base_uri`
uri the segment comes from in URI hierarchy. ex.: http://example.com/path/to
'''
tag = ext_x_map
if self.gap:
output.append(',GAP=%s' % self.gap)
return ''.join(output)
def __str__(self):
return self.dumps(None)
class PartialSegmentList(list, GroupedBasePathMixin):
def __str__(self):
output = [str(part) for part in self]
return '\n'.join(output)
class Key(BasePathMixin):
'''
Key used to encrypt the segments in a m3u8 playlist (EXT-X-KEY)
`method`
is a string. ex.: "AES-128"
`uri`
is a string. ex:: "https://priv.example.com/key.php?r=52"
`base_uri`
uri the key comes from in URI hierarchy. ex.: http://example.com/path/to
`iv`
initialization vector. a string representing a hexadecimal number. ex.: 0X12A
'''
for segment in self:
output.append(segment.dumps(last_segment))
last_segment = segment
return '\n'.join(output)
@property
def uri(self):
return [seg.uri for seg in self]
def by_key(self, key):
return [ segment for segment in self if segment.key == key ]
class PartialSegment(BasePathMixin):
'''
A partial segment from a M3U8 playlist
`uri`
a string with the segment uri
`program_date_time`
Returns the EXT-X-PROGRAM-DATE-TIME as a datetime. This field is only set
if EXT-X-PROGRAM-DATE-TIME exists for this segment
http://tools.ietf.org/html/draft-pantos-http-live-streaming-07#section-3.3.5
`current_program_date_time`
Returns a datetime of this segment, either the value of `program_date_time`
when EXT-X-PROGRAM-DATE-TIME is set or a calculated value based on previous
segments' EXT-X-PROGRAM-DATE-TIME and EXTINF values
def __str__(self):
return self.dumps()
class PartInformation(object):
def __init__(self, part_target=None):
self.part_target = part_target
def dumps(self):
return '#EXT-X-PART-INF:PART-TARGET=%s' % number_to_string(
self.part_target)
def __str__(self):
return self.dumps()
class PreloadHint(BasePathMixin):
def __init__(self, type, base_uri, uri, byterange_start=None, byterange_length=None):
self.hint_type = type
self.base_uri = base_uri
self.uri = uri
self.byterange_start = byterange_start
self.byterange_length = byterange_length
def __getitem__(self, item):
return getattr(self, item)
def dumps(self):
hint = []
hint.append('TYPE=' + self.hint_type)
hint.append('URI=' + quoted(self.uri))
for attr in ['byterange_start', 'byterange_length']:
stream_inf.append('AVERAGE-BANDWIDTH=%d' %
self.average_bandwidth)
if self.resolution is not None:
res = str(self.resolution[
0]) + 'x' + str(self.resolution[1])
stream_inf.append('RESOLUTION=' + res)
if self.frame_rate is not None:
stream_inf.append('FRAME-RATE=%g' % decimal.Decimal(self.frame_rate).quantize(decimal.Decimal('1.000')))
if self.codecs is not None:
stream_inf.append('CODECS=' + quoted(self.codecs))
if self.video_range is not None:
stream_inf.append('VIDEO-RANGE=%s' % self.video_range)
return ",".join(stream_inf)
class Media(BasePathMixin):
'''
A media object from a M3U8 playlist
https://tools.ietf.org/html/draft-pantos-http-live-streaming-16#section-4.3.4.1
`uri`
a string with the media uri
`type`
`group_id`
`language`
`assoc-language`
`name`
`default`
`autoselect`
`forced`
`instream_id`