def __init__(self, key): key = bytes_list(key) data = list(range(256)) b, n = 0, len(key) for i in range(256): b += (data[i] + key[i%n]) b &= 0xff data[i], data[b] = data[b], data[i] self.c1 = self.c2 = 0 self.data = data
def extract_strings(data, keys): fd = BytesIO(keys) keys = [fd.read(16) for i in range(U8.read(fd))] if not keys: return fd = BytesIO(data) for i in range(U32LE.read(fd)): msg = fd.read(U32LE.read(fd)) key = keys[i % len(keys)] return Decryptor(key).decrypt(msg)
def _create_flv_playlist(self, template): res = http.get(template) json = http.json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") parsed = urlparse(template) try: url_template = '{0}://{1}{2}'.format(parsed.scheme, parsed.netloc, json['template']) segment_max = reduce(lambda i, j: i + j[0], json['fragments'], 0) duration = json['duration'] except KeyError: raise PluginError('Unexpected JSON response') substreams = [ HTTPStream(self.session, url_template.replace('$fragment$', str(i))) for i in range(1, segment_max + 1) ] return FLVPlaylist(self.session, streams=substreams, duration=duration, skip_header=True, flatten_timestamps=True)
def update_chunk_info(self, result): chunk_range = result["chunkRange"] if not chunk_range: return chunk_id = int(result["chunkId"]) chunk_offset = int(result["offset"]) chunk_range = dict(map(partial(map, int), chunk_range.items())) self.chunk_ranges.update(chunk_range) self.chunk_id_min = sorted(chunk_range)[0] self.chunk_id_max = int(result["chunkId"]) self.chunks = [Chunk(i, self.format_chunk_url(i), not self.chunk_id and i == chunk_id and chunk_offset) for i in range(self.chunk_id_min, self.chunk_id_max + 1)] if self.chunk_id is None and self.chunks: self.chunk_id = chunk_id
def iter_segments(self): quality = QUALITY_MAP[self.stream.quality] for part in self.stream.parts: duration = part.get("duration") if not part.get("recording"): recording = part.get("id") extension = "part" else: recording = part.get("recording") extension = "rec" chunks = int(duration / 12) + 1 start = int(part.get("start", 0) / 12) for sequence in range(start, chunks + start): if self.closed: return self.logger.debug("Adding chunk {0}/{1}/{2} to queue", recording, quality, sequence) yield Chunk(recording, quality, sequence, extension)
def _create_flv_playlist(self, template): res = http.get(template) playlist = http.json(res, schema=_vod_playlist_schema) parsed = urlparse(template) url_template = "{0}://{1}{2}".format( parsed.scheme, parsed.netloc, playlist["template"] ) segment_max = reduce(lambda i,j: i + j[0], playlist["fragments"], 0) substreams = [HTTPStream(self.session, url_template.replace("$fragment$", str(i))) for i in range(1, segment_max + 1)] return FLVPlaylist(self.session, duration=playlist["duration"], flatten_timestamps=True, skip_header=True, streams=substreams)
def _create_flv_playlist(self, template): res = http.get(template) playlist = http.json(res, schema=_vod_playlist_schema) parsed = urlparse(template) url_template = "{0}://{1}{2}".format( parsed.scheme, parsed.netloc, playlist["template"] ) segment_max = reduce(lambda i,j: i+j[0], playlist["fragments"], 0) substreams = [HTTPStream(self.session, url_template.replace("$fragment$", str(i))) for i in range(1, segment_max + 1)] return FLVPlaylist(self.session, duration=playlist["duration"], flatten_timestamps=True, skip_header=True, streams=substreams)
def update_chunk_info(self, result): chunk_range = result["chunkRange"] if not chunk_range: return chunk_id = int(result["chunkId"]) chunk_offset = int(result["offset"]) chunk_range = dict(map(partial(map, int), chunk_range.items())) self.chunk_ranges.update(chunk_range) self.chunk_id_min = sorted(chunk_range)[0] self.chunk_id_max = int(result["chunkId"]) self.chunks = [ Chunk(i, self.format_chunk_url(i), not self.chunk_id and i == chunk_id and chunk_offset) for i in range(self.chunk_id_min, self.chunk_id_max + 1) ] if self.chunk_id is None and self.chunks: self.chunk_id = chunk_id
def _create_flv_playlist(self, template): res = http.get(template) json = http.json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") parsed = urlparse(template) try: url_template = '{0}://{1}{2}'.format( parsed.scheme, parsed.netloc, json['template'] ) segment_max = reduce(lambda i,j: i+j[0], json['fragments'], 0) duration = json['duration'] except KeyError: raise PluginError('Unexpected JSON response') substreams = [HTTPStream(self.session, url_template.replace('$fragment$', str(i))) for i in range(1, segment_max + 1)] return FLVPlaylist(self.session, streams=substreams, duration=duration, skip_header=True, flatten_timestamps=True)
def iter_tags(self, fd=None, buf=None, skip_header=None): flags = U8.read(fd) quality = flags & 15 version = flags >> 4 lookup_size = U16BE.read(fd) enc_table = fd.read(lookup_size) key = b"" iv = b"" for i in range(16): key += fd.read(1) iv += fd.read(1) if not (key and iv): return dec_table = self.decrypt_data(key, iv, enc_table) dstream = BytesIO(dec_table) # Decode lookup table (ported from K-S-V BeatConvert.php) while True: flags = U8.read(dstream) if not flags: break typ = flags >> 4 encrypted = (flags & 4) > 0 keyframe = (flags & 2) > 0 config = (flags & 1) > 0 time = U32BE.read(dstream) data_length = U32BE.read(dstream) if encrypted: raw_length = U32BE.read(dstream) else: raw_length = data_length # Decrypt encrypted tags data = fd.read(data_length) if encrypted: data = self.decrypt_data(key, iv, data) data = data[:raw_length] # Create video tag if typ == 1: if version == 2: if config: avc = AVCVideoData(AVC_PACKET_TYPE_SEQUENCE_HEADER, data=data) else: avc = AVCVideoData(AVC_PACKET_TYPE_NALU, data=data) if keyframe: videodata = VideoData(VIDEO_FRAME_TYPE_KEY_FRAME, VIDEO_CODEC_ID_AVC, avc) else: videodata = VideoData(VIDEO_FRAME_TYPE_INTER_FRAME, VIDEO_CODEC_ID_AVC, avc) else: videodata = RawData(data) yield Tag(TAG_TYPE_VIDEO, time, videodata) # Create audio tag if typ == 2: if version == 2: if config: aac = AACAudioData(AAC_PACKET_TYPE_SEQUENCE_HEADER, data) else: aac = AACAudioData(AAC_PACKET_TYPE_RAW, data) audiodata = AudioData(codec=AUDIO_CODEC_ID_AAC, rate=AUDIO_RATE_44_KHZ, bits=AUDIO_BIT_RATE_16, type=AUDIO_TYPE_STEREO, data=aac) else: audiodata = RawData(data) yield Tag(TAG_TYPE_AUDIO, time, audiodata)