def _create_video_clip(self, chunks, start_offset, stop_offset): playlist_duration = stop_offset - start_offset playlist_offset = 0 playlist_streams = [] playlist_tags = [] for chunk in chunks: chunk_url = chunk.get("url") chunk_length = chunk.get("length") chunk_start = playlist_offset chunk_stop = chunk_start + chunk_length chunk_stream = HTTPStream(self.session, chunk_url) if start_offset >= chunk_start and start_offset <= chunk_stop: headers = extract_flv_header_tags(chunk_stream) if not headers.metadata: raise StreamError( "Missing metadata tag in the first chunk") metadata = headers.metadata.data.value keyframes = metadata.get("keyframes") if not keyframes: raise StreamError( "Missing keyframes info in the first chunk") keyframe_offset = None keyframe_offsets = keyframes.get("filepositions") keyframe_times = [ playlist_offset + t for t in keyframes.get("times") ] for time, offset in izip(keyframe_times, keyframe_offsets): if time > start_offset: break keyframe_offset = offset if keyframe_offset is None: raise StreamError("Unable to find a keyframe to seek to " "in the first chunk") chunk_headers = dict( Range="bytes={0}-".format(int(keyframe_offset))) chunk_stream = HTTPStream(self.session, chunk_url, headers=chunk_headers) playlist_streams.append(chunk_stream) for tag in headers: playlist_tags.append(tag) elif chunk_start >= start_offset and chunk_start < stop_offset: playlist_streams.append(chunk_stream) playlist_offset += chunk_length return FLVPlaylist(self.session, playlist_streams, tags=playlist_tags, duration=playlist_duration)
def create_decryptor(self, key, sequence): if key.method != "AES-128": raise StreamError("Unable to decrypt cipher {0}", key.method) if not key.uri: raise StreamError("Missing URI to decryption key") if self.key_uri != key.uri: zoom_key = self.reader.stream.session.options.get("zoom-key") saw_key = self.reader.stream.session.options.get("saw-key") your_key = self.reader.stream.session.options.get("your-key") if zoom_key: uri = 'http://www.zoomtv.me/k.php?q=' + base64.urlsafe_b64encode( zoom_key + base64.urlsafe_b64encode(key.uri)) elif saw_key: if 'foxsportsgo' in key.uri: _tmp = key.uri.split('/') uri = urljoin(saw_key, '/m/fream?p=' + _tmp[-4] + '&k=' + _tmp[-1]) elif 'nlsk.neulion' in key.uri: _tmp = key.uri.split('?') uri = urljoin(saw_key, '/m/stream?' + _tmp[-1]) elif 'nhl.com' in key.uri: _tmp = key.uri.split('/') uri = urljoin(saw_key, '/m/streams?ci=' + _tmp[-3] + '&k=' + _tmp[-1]) elif your_key: if 'mlb.com' in key.uri: _tmp = key.uri.split('?') uri = urljoin(your_key, '/mlb/get_key/' + _tmp[-1]) elif 'espn3/auth' in key.uri: _tmp = key.uri.split('?') uri = urljoin(your_key, '/ncaa/get_key/' + _tmp[-1]) elif 'nhl.com' in key.uri: _tmp = key.uri.split('nhl.com/') uri = urljoin(your_key, '/nhl/get_key/' + _tmp[-1]) else: uri = key.uri else: uri = key.uri res = self.session.http.get(uri, exception=StreamError, **self.reader.request_params) self.key_data = res.content self.key_uri = key.uri iv = key.iv or num_to_iv(sequence) if _android_ssl: return enc(self.key_data, iv) elif _oscrypto: return AES(self.key_data, iv) else: return AES.new(self.key_data, AES.MODE_CBC, iv)
def process_sequences(self, playlist, sequences): first_sequence, last_sequence = sequences[0], sequences[-1] if first_sequence.segment.key and first_sequence.segment.key.method != "NONE": self.logger.debug("Segments in this playlist are encrypted") if not CAN_DECRYPT: raise StreamError("No crypto lib installed to decrypt this stream") self.playlist_changed = ([s.num for s in self.playlist_sequences] != [s.num for s in sequences]) self.playlist_reload_time = (playlist.target_duration or last_sequence.segment.duration) self.playlist_sequences = sequences if not self.playlist_changed: self.playlist_reload_time = max(self.playlist_reload_time / 2, 1) if playlist.is_endlist: self.playlist_end = last_sequence.num if self.playlist_sequence < 0: if self.playlist_end is None: edge_index = -(min(len(sequences), max(int(self.live_edge), 1))) edge_sequence = sequences[edge_index] self.playlist_sequence = edge_sequence.num else: self.playlist_sequence = first_sequence.num
def open(self): if not CAN_DECRYPT: raise StreamError( "pyCrypto needs to be installed to decrypt this stream") reader = BeatStreamReader(self) reader.open() return reader
def fetch_module_info(self): self.logger.debug("Fetching module info") conn = create_ums_connection("channel", self.stream.channel_id, self.stream.page_url, self.stream.password, exception=StreamError) try: result = conn.process_packets(invoked_method="moduleInfo", timeout=10) except (IOError, librtmp.RTMPError) as err: raise StreamError("Failed to get module info: {0}".format(err)) finally: conn.close() return validate_module_info(result)
def create_decryptor(self, key, sequence): if key.method != "AES-128": raise StreamError("Unable to decrypt cipher {0}", key.method) if not key.uri: raise StreamError("Missing URI to decryption key") if self.key_uri != key.uri: zoom_key = self.reader.stream.session.options.get("zoom-key") zuom_key = self.reader.stream.session.options.get("zuom-key") livecam_key = self.reader.stream.session.options.get("livecam-key") saw_key = self.reader.stream.session.options.get("saw-key") your_key = self.reader.stream.session.options.get("your-key") mama_key = self.reader.stream.session.options.get("mama-key") if zoom_key: uri = 'http://www.zoomtv.me/k.php?q='+base64.urlsafe_b64encode(zoom_key+base64.urlsafe_b64encode(key.uri)) elif zuom_key: uri = 'http://www.zuom.xyz/k.php?q='+base64.urlsafe_b64encode(zuom_key+base64.urlsafe_b64encode(key.uri)) elif livecam_key: h = urlparse.urlparse(urllib.unquote(livecam_key)).netloc q = urlparse.urlparse(urllib.unquote(livecam_key)).query uri = 'http://%s/kaes?q='%h+base64.urlsafe_b64encode(q+base64.b64encode(key.uri)) elif saw_key: if 'foxsportsgo' in key.uri: _tmp = key.uri.split('/') uri = urljoin(saw_key,'/m/fream?p='+_tmp[-4]+'&k='+_tmp[-1]) elif 'nlsk.neulion' in key.uri: _tmp = key.uri.split('?') uri = urljoin(saw_key,'/m/stream?'+_tmp[-1]) elif 'nlsk' in key.uri: _tmp = key.uri.split('?') uri = 'http://bile.level303.club/m/stream?'+_tmp[-1] elif 'nhl.com' in key.uri: _tmp = key.uri.split('/') uri = urljoin(saw_key,'/m/streams?ci='+_tmp[-3]+'&k='+_tmp[-1]) else: uri = key.uri elif mama_key: if 'nlsk' in key.uri: _tmp = key.uri.split('&url=') uri = 'http://mamahd.in/nba?url=' + _tmp[-1] elif your_key: if 'mlb.com' in key.uri: _tmp = key.uri.split('?') uri = urljoin(your_key,'/mlb/get_key/'+_tmp[-1]) elif 'espn3/auth' in key.uri: _tmp = key.uri.split('?') uri = urljoin(your_key,'/ncaa/get_key/'+_tmp[-1]) elif 'nhl.com' in key.uri: _tmp = key.uri.split('nhl.com/') uri = urljoin(your_key,'/nhl/get_key/'+_tmp[-1]) else: uri = key.uri else: uri = key.uri res = self.session.http.get(uri, exception=StreamError, **self.reader.request_params) self.key_data = res.content self.key_uri = key.uri iv = key.iv or num_to_iv(sequence) if _android_ssl: return enc(self.key_data, iv) elif _oscrypto: return AES(self.key_data, iv) else: return AES.new(self.key_data, AES.MODE_CBC, iv)
def _get_streams(self): self.logger.debug("Fetching stream info") headers = {"Referer": self.url} res = urlget(self.url, headers=headers) match = re.search("flashvars.*?cid[^\d]+?(\d+)", res.text) if not match: raise NoStreamsError(self.url) headers = {"Referer": self.SWFURL} form = dict(cid=match.group(1), watchTime="0", firstConnect="1", ip="NaN") res = urlopen(self.APIURL, data=form, headers=headers) params = parse_qsd(res.text) if "0" in params and int(params["0"]) <= 0: raise StreamError("Server refused to send required parameters.") rtmp = params["10"] playpath = params["11"] multibitrate = int(params["20"]) premiumuser = params["5"] blocktype = int(params["13"]) if blocktype != 0: if blocktype == 1: blocktime = params["14"] reconnectiontime = params["16"] msg = ("You have crossed free viewing limit. ", "You have been blocked for %s minutes. " % blocktime, "Try again in %s minutes." % reconnectiontime) raise StreamError(msg) elif blocktype == 11: raise StreamError("No free slots available.") if "73" in params: token = params["73"] else: raise StreamError("Server seems busy, please try after some time.") if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Weeb plugin") streams = {} if multibitrate: streams["low"] = RTMPStream( self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) playpath += "HI" streams["live"] = RTMPStream( self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) return streams