def _get_rtmp_streams(self, swfurl): if not RTMPStream.is_usable(self.session): raise NoStreamsError(self.url) self.logger.debug("Fetching RTMP stream info") res = http.get(swfurl) swf = swfdecompress(res.content) match = re.search("customURL[^h]+(https://.*?)\\\\", swf) if not match: raise NoStreamsError(self.url) res = http.get(match.group(1)) rtmp, playpath = rtmpparse(res.text) params = { "rtmp": rtmp, "pageUrl": self.url, "playpath": playpath, "live": True } match = re.search("file[^h]+(https?://.*?.swf)", swf) if match: params["swfUrl"] = match.group(1) return RTMPStream(self.session, params)
def _get_streams(self): self.channelname = self._get_channel_name(self.url) if not self.channelname: raise NoStreamsError(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams() streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams() for name, stream in hlsstreams.items(): if name in streams: streams[name] = [streams[name], stream] else: streams[name] = stream except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_live_streams(self, *args, **kwargs): streams = defaultdict(list) if RTMPStream.is_usable(self.session): try: for name, stream in self._get_desktop_streams(*args, **kwargs).items(): streams[name].append(stream) except PluginError as err: self.logger.error("Error when fetching desktop streams: {0}", err) except NoStreamsError: pass else: self.logger.warning("rtmpdump is required to access the desktop " "streams, but it could not be found") try: for name, stream in self._get_mobile_streams(*args, **kwargs).items(): # Justin.tv streams have a iphone prefix, so let's # strip it to keep it consistent with Twitch. name = name.replace("iphone", "") streams[name].append(stream) except PluginError as err: self.logger.error("Error when fetching mobile streams: {0}", err) except NoStreamsError: pass return streams
def _get_streams(self): channelid = urlparse( self.url).path.rstrip("/").rpartition("/")[-1].lower() self.logger.debug("Fetching stream info") headers = {"Referer": self.url} options = dict(id=channelid) res = urlget(self.StreamInfoURL, headers=headers, params=options) json = res_json(res, "stream info JSON") if not isinstance(json, dict): raise PluginError("Invalid JSON response") if not ("rtmp" in json and "streamname" in json): raise NoStreamsError(self.url) if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Owncast plugin") rtmp = json["rtmp"] playpath = json["streamname"] streams = {} streams["live"] = RTMPStream( self.session, { "rtmp": rtmp, "pageUrl": self.url, "swfUrl": self.SWFURL, "playpath": playpath, "live": True }) return streams
def _get_streams(self): self.channelname = self._get_channel_name(self.url) if not self.channelname: raise NoStreamsError(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams() streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams() if len(streams) > 0: hlssuffix = "_hls" else: hlssuffix = "" for name, stream in hlsstreams.items(): streams[name + hlssuffix] = stream except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_live_streams(self): streams = defaultdict(list) if RTMPStream.is_usable(self.session): try: for name, stream in self._get_desktop_streams().items(): streams[name].append(stream) except PluginError as err: self.logger.error("Error when fetching desktop streams: {0}", err) except NoStreamsError: pass else: self.logger.warning("rtmpdump is not usable, " "only mobile streams may be available") try: for name, stream in self._get_mobile_streams().items(): # Justin.tv streams have a iphone prefix, so let's # strip it to keep it consistent with Twitch. name = name.replace("iphone", "") streams[name].append(stream) except PluginError as err: self.logger.error("Error when fetching mobile streams: {0}", err) except NoStreamsError: pass return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Filmon plugin") self.logger.debug("Fetching stream info") self.rsession = requests.session() res = urlget(self.url, session=self.rsession) match = re.search("movie_id=(\d+)", res.text) if match: return self._get_vod_stream(match.group(1)) match = re.search("/channels/(\d+)/extra_big_logo.png", res.text) if not match: return channel_id = match.group(1) streams = {} for quality in ("low", "high"): try: streams[quality] = self._get_stream(channel_id, quality) except NoStreamsError: pass return streams
def _get_streams(self, type): self.channelname = self._get_channel_name(self.url) if not self.channelname: raise NoStreamsError(self.url) streams = {} if type in (None, StreamType.RTMP): if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams() streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") if type in (None, StreamType.HLS): try: hlsstreams = self._get_hls_streams() if len(streams) > 0: hlssuffix = "_hls" else: hlssuffix = "" for name, stream in hlsstreams.items(): streams[name + hlssuffix] = stream except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): self.logger.warning("rtmpdump is not usable, only HDS streams will be available") self.logger.debug("Fetching stream info") match = re.search("/\w*/(live|video)*/(\d+)", self.url) if not match: return stream_id = match.group(2) res = http.get(API_URL, params=dict(ak="web", id=stream_id)) root = parse_xml(res.text.encode("utf8")) streams = {} for formitaet in root.iter('formitaet'): url = formitaet.find('url').text quality = formitaet.find('quality').text if formitaet.get('basetype') == "h264_aac_f4f_http_f4m_http": hds_streams = HDSStream.parse_manifest(self.session, url) streams.update(hds_streams) elif formitaet.get('basetype') == 'h264_aac_mp4_rtmp_zdfmeta_http': streams[quality] = RTMPStream(self.session, { "rtmp": self._get_stream(url), "pageUrl": self.url, }) return streams
def _get_streams(self): channelid = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower() self.logger.debug("Fetching stream info") headers = {"Referer": self.url} options = dict(id=channelid) res = urlget(self.StreamInfoURL, headers=headers, params=options) json = res_json(res, "stream info JSON") if not isinstance(json, dict): raise PluginError("Invalid JSON response") if not ("rtmp" in json and "streamname" in json): raise NoStreamsError(self.url) if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Owncast plugin") rtmp = json["rtmp"] playpath = json["streamname"] streams = {} streams["live"] = RTMPStream( self.session, {"rtmp": rtmp, "pageUrl": self.url, "swfUrl": self.SWFURL, "playpath": playpath, "live": True} ) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Filmon plugin") self.logger.debug("Fetching stream info") res = http.get(self.url) match = re.search("movie_id=(\d+)", res.text) if match: return self._get_vod_stream(match.group(1)) match = re.search("/channels/(\d+)/extra_big_logo.png", res.text) if not match: return channel_id = match.group(1) streams = {} for quality in ("low", "high"): try: streams[quality] = self._get_stream(channel_id, quality) except NoStreamsError: pass return streams
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url) match = re.search("var current_channel = (.*);", res.text) if match: json = parse_json(match.group(1)) else: raise NoStreamsError(self.url) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not "streams" in json: raise NoStreamsError(self.url) if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Filmon plugin") match = re.search("var flash_config = (.*);", res.text) if match: config = parse_json(match.group(1)) if "streamer" in config: self.SWFURL = urljoin(self.SWFURL, config["streamer"]) streams = {} for stream in json["streams"]: if not ("url" in stream and "name" in stream): continue parsed = urlparse(stream["url"]) if not parsed.scheme.startswith("rtmp"): continue if parsed.query: app = "{0}?{1}".format(parsed.path[1:], parsed.query) else: app = parsed.path[1:] name = stream["quality"] streams[name] = RTMPStream( self.session, { "rtmp": stream["url"], "pageUrl": self.url, "swfUrl": self.SWFURL, "playpath": stream["name"], "app": app, "live": True }) return streams
def _get_streams(self): # If email option given, try to login if self.options.get("email"): res = http.get(self.LOGINPAGEURL) match = re.search('<meta content="([^"]+)" name="csrf-token"', res.text) if not match: raise PluginError("Missing CSRF Token: " + self.LOGINPAGEURL) csrf_token = match.group(1) email = self.options.get("email") password = self.options.get("password") res = http.post( self.LOGINPOSTURL, data={ 'authenticity_token': csrf_token, 'channel_id': '', 'commit': 'Login', 'plan_id': '', 'session[email]': email, 'session[password]': password, 'utf8': "\xE2\x9C\x93", # Check Mark Character }) self.logger.debug("Login account info: {0}", res.text) result = http.json(res) if result.get('email', 'no-mail') != email: raise PluginError("Invalid account") res = http.get(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(res.text) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning( "rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(res.text) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams_from_rtmp(self): password = self.options.get("password") module_info = self._get_module_info("channel", self.channel_id, password) if not module_info: raise NoStreamsError(self.url) providers = module_info.get("stream") if providers == "offline": raise NoStreamsError(self.url) elif not isinstance(providers, list): raise PluginError("Invalid stream info: {0}".format(providers)) streams = {} for provider in filter(valid_provider, providers): provider_url = provider.get("url") provider_name = provider.get("name") provider_streams = provider.get("streams") for stream_index, stream_info in enumerate(provider_streams): stream = None stream_height = int(stream_info.get("height", 0)) stream_name = stream_info.get("description") if not stream_name: if stream_height: if not stream_info.get("isTranscoded"): stream_name = "{0}p+".format(stream_height) else: stream_name = "{0}p".format(stream_height) else: stream_name = "live" if stream_name in streams: provider_name_clean = provider_name.replace("uhs_", "") stream_name += "_alt_{0}".format(provider_name_clean) if provider_name.startswith("uhs_"): stream = UHSStream(self.session, self.channel_id, self.url, provider_name, stream_index, password) elif (provider_url.startswith("rtmp") and RTMPStream.is_usable(self.session)): playpath = stream_info.get("streamName") stream = self._create_rtmp_stream(provider_url, playpath) if stream: streams[stream_name] = stream return streams
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url) match = re.search("var current_channel = (.*);", res.text) if match: json = parse_json(match.group(1)) else: raise NoStreamsError(self.url) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not "streams" in json: raise NoStreamsError(self.url) if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Filmon plugin") match = re.search("var flash_config = (.*);", res.text) if match: config = parse_json(match.group(1)) if "streamer" in config: self.SWFURL = urljoin(self.SWFURL, config["streamer"]) streams = {} for stream in json["streams"]: if not ("url" in stream and "name" in stream): continue parsed = urlparse(stream["url"]) if not parsed.scheme.startswith("rtmp"): continue if parsed.query: app = "{0}?{1}".format(parsed.path[1:], parsed.query) else: app = parsed.path[1:] name = stream["quality"] streams[name] = RTMPStream(self.session, { "rtmp": stream["url"], "pageUrl": self.url, "swfUrl": self.SWFURL, "playpath": stream["name"], "app": app, "live": True }) return streams
def _get_streams(self): country_code = urlparse(self.url).netloc.split(".")[0] self.logger.debug("Fetching stream info") res = urlget(self.APIURL) json = res_json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not ("primary" in json or "secondary" in json): raise PluginError("Invalid JSON response") if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Euronews plugin") streams = {} self.logger.debug("Euronews Countries:{0}", " ".join(json["primary"].keys())) if not (country_code in json["primary"] or country_code in json["secondary"]): res = urlget(self.GEOIPURL) geo = res_json(res) if isinstance(json, dict) and "country_code" in geo: country_code = geo["country_code"].lower() if not (country_code in json["primary"] or country_code in json["secondary"]): country_code = "en" else: country_code = "en" for site in ("primary", "secondary"): for quality in json[site][country_code]["rtmp_flash"]: stream = json[site][country_code]["rtmp_flash"][quality] name = quality + "k" if site == "secondary": name += "_alt" streams[name] = RTMPStream( self.session, { "rtmp": stream["server"], "playpath": stream["name"], "swfUrl": self.SWFURL, "live": True }) if len(streams) == 0: raise NoStreamsError(self.url) return streams
def _get_streams(self): # If email option given, try to login if self.options.get("email"): res = http.get(self.LOGINPAGEURL) match = re.search('<meta content="([^"]+)" name="csrf-token"', res.text) if not match: raise PluginError("Missing CSRF Token: " + self.LOGINPAGEURL) csrf_token = match.group(1) email = self.options.get("email") password = self.options.get("password") res = http.post( self.LOGINPOSTURL, data={ "authenticity_token": csrf_token, "channel_id": "", "commit": "Login", "plan_id": "", "session[email]": email, "session[password]": password, "utf8": "\xE2\x9C\x93", # Check Mark Character }, ) self.logger.debug("Login account info: {0}", res.text) result = http.json(res) if result.get("email", "no-mail") != email: raise PluginError("Invalid account") res = http.get(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(res.text) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(res.text) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams_from_amf(self): if not RTMPStream.is_usable(self.session): raise NoStreamsError(self.url) res = urlget(AMF_URL.format(self.channel_id)) try: packet = AMFPacket.deserialize(BytesIO(res.content)) except (IOError, AMFError) as err: raise PluginError("Failed to parse AMF packet: {0}".format(err)) for message in packet.messages: if message.target_uri == "/1/onResult": result = message.value break else: raise PluginError("No result found in AMF packet") streams = {} stream_name = result.get("streamName") if stream_name: cdn = result.get("cdnUrl") or result.get("fmsUrl") if cdn: stream = self._create_rtmp_stream(cdn, stream_name) if "videoCodec" in result and result["videoCodec"][ "height"] > 0: stream_name = "{0}p".format( int(result["videoCodec"]["height"])) else: stream_name = "live" streams[stream_name] = stream else: self.logger.warning("Missing cdnUrl and fmsUrl from result") stream_versions = result.get("streamVersions") if stream_versions: for version, info in stream_versions.items(): stream_version_cdn = info.get("streamVersionCdn", {}) for name, cdn in filter(valid_cdn, stream_version_cdn.items()): stream = self._create_rtmp_stream(cdn["cdnStreamUrl"], cdn["cdnStreamName"]) stream_name = "live_alt_{0}".format(name) streams[stream_name] = stream return streams
def _get_streams(self): params = parse_qsd(urlparse(self.url).query) if not 'watch' in params: raise NoStreamsError(self.url) channel = params['watch'] if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable but required by Picarto plugin") streams = {} streams["live"] = RTMPStream(self.session, { "rtmp": "rtmp://199.189.86.17/dsapp/{0}.flv".format(channel), "pageUrl": self.url, "live": True }) return streams
def _get_streams(self): match = re.search("/v/(\d+)", self.url) if not match: return vid = match.group(1) params = dict(client_name="Bambuser AS2", context="b_broadcastpage", raw_user_input=1, api_key="005f64509e19a868399060af746a00aa", vid=vid, r=random.random()) self.logger.debug("Fetching stream info") res = http.get(PLAYER_URL, params=params) json = http.json(res) error = json and json.get("errorCode") if error: error = error and json.get("error") self.logger.error(error) return json = verifyjson(json, "result") playpath = verifyjson(json, "id") url = verifyjson(json, "url") (width, height) = verifyjson(json, "size").split("x") name = "{0}p".format(height) parsed = urlparse(url) streams = {} if parsed.scheme.startswith("rtmp"): if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Bambuser plugin") streams[name] = RTMPStream( self.session, { "rtmp": url, "playpath": playpath, "pageUrl": self.url, "live": True }) elif parsed.scheme == "http": streams[name] = HTTPStream(self.session, url) return streams
def _get_streams_from_amf(self): if not RTMPStream.is_usable(self.session): raise NoStreamsError(self.url) res = urlget(AMF_URL.format(self.channel_id)) try: packet = AMFPacket.deserialize(BytesIO(res.content)) except (IOError, AMFError) as err: raise PluginError("Failed to parse AMF packet: {0}".format(err)) for message in packet.messages: if message.target_uri == "/1/onResult": result = message.value break else: raise PluginError("No result found in AMF packet") streams = {} stream_name = result.get("streamName") if stream_name: cdn = result.get("cdnUrl") or result.get("fmsUrl") if cdn: stream = self._create_rtmp_stream(cdn, stream_name) if "videoCodec" in result and result["videoCodec"]["height"] > 0: stream_name = "{0}p".format(int(result["videoCodec"]["height"])) else: stream_name = "live" streams[stream_name] = stream else: self.logger.warning("Missing cdnUrl and fmsUrl from result") stream_versions = result.get("streamVersions") if stream_versions: for version, info in stream_versions.items(): stream_version_cdn = info.get("streamVersionCdn", {}) for name, cdn in filter(valid_cdn, stream_version_cdn.items()): stream = self._create_rtmp_stream(cdn["cdnStreamUrl"], cdn["cdnStreamName"]) stream_name = "live_alt_{0}".format(name) streams[stream_name] = stream return streams
def _get_streams(self): country_code = urlparse(self.url).netloc.split(".")[0] self.logger.debug("Fetching stream info") res = http.get(self.APIURL) json = http.json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not ("primary" in json or "secondary" in json): raise PluginError("Invalid JSON response") if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Euronews plugin") streams = {} self.logger.debug("Euronews Countries:{0}", " ".join(json["primary"].keys())) if not (country_code in json["primary"] or country_code in json["secondary"]): res = http.get(self.GEOIPURL) geo = http.json(res) if isinstance(json, dict) and "country_code" in geo: country_code = geo["country_code"].lower() if not (country_code in json["primary"] or country_code in json["secondary"]): country_code = "en" else: country_code = "en" for site in ("primary", "secondary"): for quality in json[site][country_code]["rtmp_flash"]: stream = json[site][country_code]["rtmp_flash"][quality] name = quality + "k" if site == "secondary": name += "_alt" streams[name] = RTMPStream(self.session, { "rtmp": stream["server"], "playpath" : stream["name"], "swfUrl": self.SWFURL, "live": True }) if len(streams) == 0: raise NoStreamsError(self.url) return streams
def _get_streams(self): params = parse_qsd(urlparse(self.url).query) if not 'watch' in params: raise NoStreamsError(self.url) channel = params['watch'] if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable but required by Picarto plugin") streams = {} streams["live"] = RTMPStream( self.session, { "rtmp": "rtmp://199.189.86.17/dsapp/{0}.flv".format(channel), "pageUrl": self.url, "live": True }) return streams
def _get_streams(self): self.channelname = self._get_channel_name(self.url) if not self.channelname: raise NoStreamsError(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams() for name, stream in rtmpstreams.items(): if "iphone" in name: name = name.replace("iphone", "mobile_") streams[name] = stream except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning( "rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams() for name, stream in hlsstreams.items(): if name in ("high", "low"): name = "mobile_{0}".format(name) if "iphone" in name: name = name.replace("iphone", "mobile_") if name in streams: streams[name] = [streams[name], stream] else: streams[name] = stream except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): match = re.search("/v/(\d+)", self.url) if not match: return vid = match.group(1) params = dict(client_name="Bambuser AS2", context="b_broadcastpage", raw_user_input=1, api_key="005f64509e19a868399060af746a00aa", vid=vid, r=random.random()) self.logger.debug("Fetching stream info") res = http.get(PLAYER_URL, params=params) json = http.json(res) error = json and json.get("errorCode") if error: error = error and json.get("error") self.logger.error(error) return json = verifyjson(json, "result") playpath = verifyjson(json, "id") url = verifyjson(json, "url") (width, height) = verifyjson(json, "size").split("x") name = "{0}p".format(height) parsed = urlparse(url) streams = {} if parsed.scheme.startswith("rtmp"): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Bambuser plugin") streams[name] = RTMPStream(self.session, { "rtmp": url, "playpath": playpath, "pageUrl": self.url, "live": True }) elif parsed.scheme == "http": streams[name] = HTTPStream(self.session, url) return streams
def _get_streams(self): res = urlget(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(res.text) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(res.text) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Filmon_us plugin") streams = {} try: # history video if "filmon.us/history" in self.url or "filmon.us/video/history/hid" in self.url: streams['default'] = self._get_history() # uploaded video elif "filmon.us/video" in self.url: streams['default'] = self._get_stream_upload() # live video else: streams['default'] = self._get_stream_live() except NoStreamsError: pass return streams
def _get_streams(self): channelname = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower() streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(channelname) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(channelname) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): self.channelname = self._get_channel_name(self.url) if not self.channelname: raise NoStreamsError(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams() for name, stream in rtmpstreams.items(): if "iphone" in name: name = name.replace("iphone", "mobile_") streams[name] = stream except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning("rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams() for name, stream in hlsstreams.items(): if name in ("high", "low"): name = "mobile_{0}".format(name) if "iphone" in name: name = name.replace("iphone", "mobile_") if name in streams: streams[name] = [streams[name], stream] else: streams[name] = stream except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Filmon_us plugin") streams = {} try: # history video if "filmon.us/history" in self.url or "filmon.us/video/history/hid" in self.url: streams['default'] = self._get_history() # uploaded video elif "filmon.us/video" in self.url: streams['default'] = self._get_stream_upload() # live video else: streams['default'] = self._get_stream_live() except NoStreamsError: pass return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Hashd plugin") self.logger.debug("Fetching stream info") res = http.get(self.url.rstrip("/").lower()+".json?first=true") json = http.json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") elif not ("live" in json or "file" in json): raise PluginError("Invalid JSON response") if "file" in json: streams = self._parse_vod(json) elif json["live"]: streams = self._parse_live(json) else: raise NoStreamsError(self.url) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Furstream plugin") self.logger.debug("Fetching stream info") res = http.get(self.url) match = re.search("rtmp://(?:(?!\").)*", res.text) if match: self.logger.debug("Stream URL: " + match.group(0)) rtmp = match.group(0) else: return streams = {} streams["live"] = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "live": True }) return streams
def _get_live_streams(self): self.channel_id = self._get_channel_id(self.url) if not self.channel_id: raise NoStreamsError(self.url) streams = defaultdict(list) if not RTMPStream.is_usable(self.session): self.logger.warning("rtmpdump is not usable. " "Not all streams may be available.") if HAS_LIBRTMP: desktop_streams = self._get_streams_from_rtmp else: self.logger.warning("python-librtmp is not installed. " "Not all streams may be available.") desktop_streams = self._get_streams_from_amf try: for name, stream in desktop_streams().items(): streams[name].append(stream) except PluginError as err: self.logger.error("Unable to fetch desktop streams: {0}", err) except NoStreamsError: pass try: mobile_streams = self._get_hls_streams( wait_for_transcode=not streams) for name, stream in mobile_streams.items(): streams[name].append(stream) except PluginError as err: self.logger.error("Unable to fetch mobile streams: {0}", err) except NoStreamsError: pass return streams
def _get_streams(self): res = urlget(self.url) streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(res.text) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning( "rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(res.text) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_live_streams(self): self.channel_id = self._get_channel_id(self.url) if not self.channel_id: raise NoStreamsError(self.url) streams = defaultdict(list) if not RTMPStream.is_usable(self.session): self.logger.warning("rtmpdump is not usable. " "Not all streams may be available.") if HAS_LIBRTMP: desktop_streams = self._get_streams_from_rtmp else: self.logger.warning("python-librtmp is not installed. " "Not all streams may be available.") desktop_streams = self._get_streams_from_amf try: for name, stream in desktop_streams().items(): streams[name].append(stream) except PluginError as err: self.logger.error("Unable to fetch desktop streams: {0}", err) except NoStreamsError: pass try: mobile_streams = self._get_hls_streams(wait_for_transcode=not streams) for name, stream in mobile_streams.items(): streams[name].append(stream) except PluginError as err: self.logger.error("Unable to fetch mobile streams: {0}", err) except NoStreamsError: pass return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError( "rtmpdump is not usable and required by Cybergame plugin") if "/videos/" in self.url: return self._get_vod_streams() self.logger.debug("Fetching live stream info") res = http.get(self.url) match = re.search("channel=([^\"]+)", res.text) if not match: raise NoStreamsError(self.url) channelname = match.group(1) res = http.get(CONFIG_URL, params=dict(c=channelname, ports="y")) json = http.json(res) servers = json.get("servers") if not servers: raise NoStreamsError(self.url) alternative = "" streams = {} for server in servers: srv, port = server.split(":") params = dict(channel=channelname, server=srv, port=port) tmpstreams = self._get_rtmp_streams(params, alternative) streams.update(tmpstreams) if not alternative: alternative = "_alt" else: break return streams
def _get_streams(self): channelname = urlparse( self.url).path.rstrip("/").rpartition("/")[-1].lower() streams = {} if RTMPStream.is_usable(self.session): try: rtmpstreams = self._get_rtmp_streams(channelname) streams.update(rtmpstreams) except PluginError as err: self.logger.error("Error when fetching RTMP stream info: {0}", str(err)) else: self.logger.warning( "rtmpdump is not usable, only HLS streams will be available") try: hlsstreams = self._get_hls_streams(channelname) streams.update(hlsstreams) except PluginError as err: self.logger.error("Error when fetching HLS stream info: {0}", str(err)) return streams
def _get_streams(self): if not RTMPStream.is_usable(self.session): raise PluginError("rtmpdump is not usable and required by Cybergame plugin") if "/videos/" in self.url: return self._get_vod_streams() self.logger.debug("Fetching live stream info") res = http.get(self.url) match = re.search("channel=([^\"]+)", res.text) if not match: raise NoStreamsError(self.url) channelname = match.group(1) res = http.get(CONFIG_URL, params=dict(c=channelname, ports="y")) json = http.json(res) servers = json.get("servers") if not servers: raise NoStreamsError(self.url) alternative = "" streams = {} for server in servers: srv, port = server.split(":") params = dict(channel=channelname, server=srv, port=port) tmpstreams = self._get_rtmp_streams(params, alternative) streams.update(tmpstreams) if not alternative: alternative = "_alt" else: break return streams
def _get_streams(self): channelid = self._get_channel_id(self.url) if not channelid: raise NoStreamsError(self.url) self.logger.debug("Fetching stream info") res = urlget(self.AMFURL.format(channelid)) try: packet = AMFPacket.deserialize(BytesIO(res.content)) except (IOError, AMFError) as err: raise PluginError(("Failed to parse AMF packet: {0}").format(str(err))) result = None for message in packet.messages: if message.target_uri == "/1/onResult": result = message.value break if not result: raise PluginError("No result found in AMF packet") streams = {} if RTMPStream.is_usable(self.session) and "streamName" in result: if "cdnUrl" in result: cdn = result["cdnUrl"] elif "fmsUrl" in result: cdn = result["fmsUrl"] else: self.logger.warning("Missing cdnUrl and fmsUrl from result") return streams if "videoCodec" in result and result["videoCodec"]["height"] > 0: streamname = "{0}p".format(int(result["videoCodec"]["height"])) else: streamname = "live" streams[streamname] = self._create_stream(cdn, result["streamName"]) if RTMPStream.is_usable(self.session) and "streamVersions" in result: for version, info in result["streamVersions"].items(): if "streamVersionCdn" in info: for name, cdn in info["streamVersionCdn"].items(): if "cdnStreamUrl" in cdn and "cdnStreamName" in cdn: cdnname = "live_alt_{0}".format(name) streams[cdnname] = self._create_stream(cdn["cdnStreamUrl"], cdn["cdnStreamName"]) # On some channels the AMF API will not return any streams, # attempt to access the HLS playlist directly instead. # # HLS streams are created on demand, so we may have to wait # for a transcode to be started. attempts = 10 playlist_url = result.get("liveHttpUrl", self.HLSPlaylistURL.format(channelid)) while attempts: try: hls_streams = HLSStream.parse_variant_playlist(self.session, playlist_url) streams.update(hls_streams) except IOError: # Channel is probably offline break if streams: break attempts -= 1 sleep(3) return streams
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
def _get_streams(self): channelname = urlparse(self.url).path.rstrip("/").rpartition("/")[-1].lower() self.logger.debug("Fetching stream info") headers = { "Referer": self.SWFURL } form = dict(cid=channelname, 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 PluginError("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 PluginError(msg) elif blocktype == 11: raise PluginError("No free slots available.") if "73" in params: token = params["73"] else: raise PluginError("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 = {} stream_name = "sd" if multibitrate: streams[stream_name] = RTMPStream(self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) playpath += "HI" stream_name = "hd" streams[stream_name] = RTMPStream(self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) return streams
def _get_streams(self): channelname = urlparse( self.url).path.rstrip("/").rpartition("/")[-1].lower() self.logger.debug("Fetching stream info") headers = {"Referer": self.SWFURL} form = dict(cid=channelname, watchTime="0", firstConnect="1", ip="NaN") res = http.post(self.APIURL, data=form, headers=headers) params = parse_qsd(res.text) if "0" in params and int(params["0"]) <= 0: raise PluginError("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 PluginError(msg) elif blocktype == 11: raise PluginError("No free slots available.") if "73" in params: token = params["73"] else: raise PluginError("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 = {} stream_name = "sd" if multibitrate: streams[stream_name] = RTMPStream( self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) playpath += "HI" stream_name = "hd" streams[stream_name] = RTMPStream( self.session, { "rtmp": "{0}/{1}".format(rtmp, playpath), "pageUrl": self.url, "swfVfy": self.SWFURL, "weeb": token, "live": True }) return streams