def test_rtmp_stream(self): stream = RTMPStream(self.session, {"rtmp": "rtmp://test.se/app/play_path", "swfVfy": "http://test.se/player.swf", "swfhash": "test", "swfsize": 123456, "playPath": "play_path"}) expected = "rtmp://test.se/app/play_path playPath=play_path swfUrl=http://test.se/player.swf swfVfy=1" self.assertEqual(expected, stream_to_url(stream)) self.assertEqual(expected, stream.to_url())
def test_rtmp_stream(self): stream = RTMPStream(self.session, {"rtmp": "rtmp://test.se/app/play_path", "swfVfy": "http://test.se/player.swf", "swfhash": "test", "swfsize": 123456, "playPath": "play_path"}) self.assertEqual( {"type": "rtmp", "args": [], "params": {"rtmp": "rtmp://test.se/app/play_path", "swfVfy": "http://test.se/player.swf", "swfhash": "test", "swfsize": 123456, "playPath": "play_path"}}, stream.__json__() )
def _get_streams(self): """ Get the config object from the page source and call the API to get the list of streams :return: """ # attempt a login self.login() res = http.get(self.url) # decode the config for the page matches = self.config_re.finditer(res.text) try: config = self.config_schema.validate(dict( [m.group("key", "value") for m in matches] )) except PluginError: return if config["selectedVideoHID"]: self.logger.debug("Found video hash ID: {0}", config["selectedVideoHID"]) api_url = urljoin(self.url, urljoin(config["videosURL"], config["selectedVideoHID"])) elif config["livestreamURL"]: self.logger.debug("Found live stream URL: {0}", config["livestreamURL"]) api_url = urljoin(self.url, config["livestreamURL"]) else: return ares = http.get(api_url) data = http.json(ares, schema=self.api_schema) viewing_urls = data["viewing_urls"] if "error" in viewing_urls: self.logger.error("Failed to load streams: {0}", viewing_urls["error"]) else: for url in viewing_urls["urls"]: try: label = "{0}p".format(url.get("res", url["label"])) except KeyError: label = "live" if url["type"] == "rtmp/mp4" and RTMPStream.is_usable(self.session): params = { "rtmp": url["src"], "pageUrl": self.url, "live": True, } yield label, RTMPStream(self.session, params) elif url["type"] == "application/x-mpegURL": for s in HLSStream.parse_variant_playlist(self.session, url["src"]).items(): yield s
def _get_streams(self): res = self.session.http.get(self.url, headers={'User-Agent': useragents.ANDROID}) match = self._video_data_re.search(res.text) if match is None: return hls_streams = HLSStream.parse_variant_playlist( self.session, match.group('hls_url'), headers={'Referer': self.url} ) for s in hls_streams.items(): yield s rtmp_video = self._flash_data_schema.validate(match.group('flash_data')) rtmp_stream = RTMPStream(self.session, { 'rtmp': rtmp_video['flashVars']['videoAppUrl'], 'playpath': rtmp_video['flashVars']['videoPlayUrl'], 'swfUrl': rtmp_video['playerUrl'] }) yield 'live', rtmp_stream
def _get_streams(self): res = http.get(self.url) stream_urls = self.stream_schema.validate(res.text) self.logger.debug("Found {0} stream URL{1}", len(stream_urls), "" if len(stream_urls) == 1 else "s") for stream_url in stream_urls: if "m3u8" in stream_url: for _, s in HLSStream.parse_variant_playlist( self.session, stream_url).items(): yield "live", s if stream_url.startswith("rtmp://"): a = stream_url.split("///") s = RTMPStream( self.session, { "rtmp": a[0], "playpath": "live", "swfVfy": "http://www.tvr.by/plugines/uppod/uppod.swf", "pageUrl": self.url }) yield "live", s
def _get_streams(self): self.session.http.headers.update({'Referer': self.url}) try: data = self.session.http.get(self.url, schema=self._data_schema) except PluginError: log.error('unable to validate _data_schema for {0}'.format( self.url)) return metadata = data.get('metadata') metadata_url = data.get('metadataUrl') if metadata_url and not metadata: metadata = self.session.http.post(metadata_url, schema=self._metadata_schema) if metadata: log.trace('{0!r}'.format(metadata)) for hls_url in [ metadata.get('hlsManifestUrl'), metadata.get('hlsMasterPlaylistUrl') ]: if hls_url is not None: yield from HLSStream.parse_variant_playlist( self.session, hls_url).items() if metadata.get('videos'): for http_stream in metadata['videos']: http_name = http_stream['name'] http_url = http_stream['url'] try: http_name = '{0}p'.format( self.QUALITY_WEIGHTS[http_name]) except KeyError: pass yield http_name, HTTPStream(self.session, http_url) if metadata.get('rtmpUrl'): yield 'live', RTMPStream(self.session, params={'rtmp': metadata['rtmpUrl']})
def _get_streams(self): page_res = http.get(self.url) match = _channel_casing_re.search(page_res.text) if not match: return {} channel = match.group("channel") visibility = match.group("visibility") channel_server_res = http.post(API_CHANNEL_INFO, data={"loadbalancinginfo": channel}) streams = {} streams["live"] = RTMPStream( self.session, { "rtmp": RTMP_URL.format(channel_server_res.text), "playpath": RTMP_PLAYPATH.format(channel, visibility), "pageUrl": self.url, "live": True }) return streams
def _get_streams(self): res = http.get(self.url, schema=_schema) streams = {} for url in res["urls"]: parsed = urlparse(url) if parsed.scheme.startswith("rtmp"): params = { "rtmp": url, "pageUrl": self.url, "live": True } if res["swf"]: params["swfVfy"] = res["swf"] stream = RTMPStream(self.session, params) streams["live"] = stream elif parsed.scheme.startswith("http"): name = splitext(parsed.path)[1][1:] stream = HTTPStream(self.session, url) streams[name] = stream return streams
def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel") headers = {"Referer": self.url} url = PLAYER_URL.format(channel) res = self.session.http.get(url, headers=headers, schema=_schema) if not res or "s" not in res: return streams = {} server = self.session.http.get(BALANCER_URL, headers=headers, schema=_rtmp_schema) playpath = "{0}?{1}".format(res["s"], res["id"]) streams["live"] = RTMPStream(self.session, { "rtmp": "rtmp://{0}/live/{1}".format(server, playpath), "pageUrl": self.url, "swfVfy": SWF_URL, "conn": "S:OK", "live": True }) return streams
def _get_streams(self): res = http.get(self.url, schema=_schema) if res["export_url"]: return self._get_live_stream(res["export_url"]) elif res["video_flashvars"]: stream = RTMPStream(self.session, { "rtmp": res["video_flashvars"]["_111pix_serverURL"], "playpath": res["video_flashvars"]["en_flash_providerName"], "swfVfy": SWF_VIDEO_URL, "pageUrl": self.url }) return dict(video=stream) elif res["standby_video"]: for stream in res["standby_video"]: stream = HTTPStream(self.session, stream["streamName"]) return dict(replay=stream) elif res["history_video"]: stream = HTTPStream(self.session, res["history_video"]) return dict(history=stream) return
def _get_streams(self): res = http.get(self.url) match = _swf_player_re.search(res.text) if match is None: return swfUrl = "http://vaughnlive.tv" + match.group(1) match = _url_re.match(self.url) params = {} params["channel"] = match.group("channel").lower() params["domain"] = DOMAIN_MAP.get(match.group("domain"), match.group("domain")) params["version"] = PLAYER_VERSION params["ms"] = random.randint(0, 999) params["random"] = random.random() info = http.get(INFO_URL.format(**params), schema=_schema) app = "live" if info["server"] in ["198.255.17.18:1337", "198.255.17.66:1337", "50.7.188.2:1337"]: if info["ingest"] == "SJC": app = "live-sjc" elif info["ingest"] == "NYC": app = "live-nyc" elif info["ingest"] == "ORD": app = "live-ord" elif info["ingest"] == "AMS": app = "live-ams" elif info["ingest"] == "DEN": app = "live-den" stream = RTMPStream(self.session, { "rtmp": "rtmp://{0}/live".format(info["server"]), "app": "{0}?{1}".format(app, info["token"]), "swfVfy": swfUrl, "pageUrl": self.url, "live": True, "playpath": "{domain}_{channel}".format(**params), }) return dict(live=stream)
def _get_streams(self): res = http.get(self.live_iframe) britecove_url = self._find_iframe(res) if britecove_url: self.logger.debug("Found britecove embed url: {0}", britecove_url) params = self._britecove_params(britecove_url) self.logger.debug("Got britecode params: {0}", params) stream_info = self._get_stream_data(**params) for source in stream_info.get("sources"): if source.get("src"): for s in HLSStream.parse_variant_playlist( self.session, source.get("src")).items(): yield s else: q = "{0}p".format(source.get("height")) s = RTMPStream( self.session, { "rtmp": source.get("app_name"), "playpath": source.get("stream_name") }) yield q, s
def _get_streams(self): match = _url_re.match(self.url) video_id = match.group("video_id") params = { "client_name": API_CLIENT_NAME, "context": API_CONTEXT, "raw_user_input": 1, "api_key": API_KEY, "vid": video_id, "r": random() } res = http.get(API_URL_VIDEO, params=params) video = http.json(res, schema=_video_schema) error = video.get("error") if error: raise PluginError(error) result = video.get("result") if not result: return url = result["url"] if url.startswith("http"): stream = HTTPStream(self.session, url) elif url.startswith("rtmp"): stream = RTMPStream( self.session, { "rtmp": url, "playpath": result["id"], "pageUrl": self.url, "live": True }) width, height = result["size"].split("x") name = "{0}p".format(height) return {name: stream}
def _get_streams(self): match = _url_re.match(self.url) if not match: return channel_name = match.group(1) res = self.session.http.get(STREAMS_URL.format(channel_name)) streams = self.session.http.json(res, schema=_streams_schema) if streams["type"] not in ("multi", "stream"): return for stream in streams["data"]: if stream["slug"] != channel_name: continue if not stream["live"]: return streams = {} try: streams.update(HLSStream.parse_variant_playlist(self.session, HLS_URL)) except IOError as e: # fix for hosted offline streams if "404 Client Error" in str(e): return raise streams["rtmp"] = RTMPStream(self.session, { "rtmp": RTMP_URL.format(stream["id"]), "pageUrl": self.url, "live": True }) return streams return
def _create_rtmp_stream(self, stream, live=True): rtmp = stream["url"] playpath = stream["name"] parsed = urlparse(rtmp) if parsed.query: app = "{0}?{1}".format(parsed.path[1:], parsed.query) else: app = parsed.path[1:] if playpath.endswith(".mp4"): playpath = "mp4:" + playpath params = { "rtmp": rtmp, "pageUrl": self.url, "swfUrl": SWF_URL, "playpath": playpath, "app": app, } if live: params["live"] = True return RTMPStream(self.session, params)
def _get_live_stream(self, export_url): res = http.get(export_url) match = _live_json_re.search(res.text) if not match: return json = parse_json(match.group(1), schema=_live_schema) streams = {} for stream in json["streams"]: stream_name = stream["quality"] parsed = urlparse(stream["url"]) stream = RTMPStream(self.session, { "rtmp": stream["url"], "app": "{0}?{1}".format(parsed.path[1:], parsed.query), "playpath": stream["name"], "swfVfy": SWF_LIVE_URL, "pageUrl": self.url, "live": True }) streams[stream_name] = stream return streams
def _get_streams(self): res = self.url streamname = _url_re.search(res).group(1) ci = http.get(API_URL.format(channel=streamname)) api_json = json.loads(ci.text) if not api_json or len(api_json) == 0: self.logger.error( "The channel {0} does not exist or is marked private".format( streamname)) return if api_json[0]["online"] == False: self.logger.error( "The channel {0} is not online".format(streamname)) return streams = {} stream = RTMPStream( self.session, { "rtmp": ROOT_URL.format(streamname), "pageUrl": PAGE_URL, "live": True, "app": "live", "flashVer": "LNX 11,2,202,280", "swfVfy": "https://www.tigerdile.com/wp-content/jwplayer.flash.swf", "playpath": streamname, }) streams["live"] = stream stream_hls = HLSStream(self.session, HLS_URL.format(channel=streamname)) streams["live_hls"] = stream_hls return streams
def _get_recorded_streams(self, video_id): if HAS_LIBRTMP: recording = self._get_module_info("recorded", video_id, schema=_recorded_schema) if not isinstance(recording.get("stream"), list): return for provider in recording["stream"]: base_url = provider.get("url") for stream_info in provider["streams"]: bitrate = int(stream_info.get("bitrate", 0)) stream_name = (bitrate > 0 and "{0}k".format(bitrate) or "recorded") url = stream_info["streamName"] if base_url: url = base_url + url if url.startswith("http"): yield stream_name, HTTPStream(self.session, url) elif url.startswith("rtmp"): params = dict(rtmp=url, pageUrl=self.url) yield stream_name, RTMPStream(self.session, params) else: self.logger.warning( "The proper API could not be used without python-librtmp " "installed. Stream URL is not guaranteed to be valid") url = RECORDED_URL.format(video_id) random_hash = "{0:02x}{1:02x}".format(randint(0, 255), randint(0, 255)) params = dict(hash=random_hash) stream = HTTPStream(self.session, url, params=params) yield "recorded", stream
def _get_streams(self): log.debug('Version 2018-07-12') log.info('This is a custom plugin. ' 'For support visit https://github.com/back-to/plugins') headers = { 'User-Agent': useragents.FIREFOX, 'Referer': self.url } self.session.http.headers.update(headers) data = self.session.http.get(self.url, schema=self._data_schema) metadata = data.get('metadata') metadata_url = data.get('metadataUrl') if metadata_url: metadata = self.session.http.post(metadata_url, schema=self._metadata_schema) if metadata: list_hls = [ metadata.get('hlsManifestUrl'), metadata.get('hlsMasterPlaylistUrl'), ] for hls_url in list_hls: if hls_url is not None: for s in HLSStream.parse_variant_playlist(self.session, hls_url).items(): yield s if metadata.get('videos'): for http_stream in metadata['videos']: http_name = http_stream['name'] http_url = http_stream['url'] try: http_name = '{0}p'.format(self.QUALITY_WEIGHTS[http_name]) except KeyError: pass yield http_name, HTTPStream(self.session, http_url) if metadata.get('rtmpUrl'): yield 'live', RTMPStream(self.session, params={'rtmp': metadata['rtmpUrl']})
def _get_streams(self): match = _url_re.match(self.url) channel = match.group("channel") self.session.http.headers.update({'User-Agent': useragents.CHROME, 'Referer': self.url}) payload = '{"liveStreamID": "%s"}' % (channel) res = self.session.http.post(API_URL, data=payload) status = _status_re.search(res.text) if not status: self.logger.info("Stream currently unavailable.") return http_url = _rtmp_re.search(res.text).group(1) https_url = http_url.replace("http:", "https:") yield "live", HTTPStream(self.session, https_url) if 'pull-rtmp' in http_url: rtmp_url = http_url.replace("http:", "rtmp:").replace(".flv", "") stream = RTMPStream(self.session, { "rtmp": rtmp_url, "live": True, "pageUrl": self.url, }) yield "live", stream if 'wansu-' in http_url: hls_url = http_url.replace(".flv", "/playlist.m3u8") else: hls_url = http_url.replace("live-hdl", "live-hls").replace(".flv", ".m3u8") s = [] for s in HLSStream.parse_variant_playlist(self.session, hls_url).items(): yield s if not s: yield "live", HLSStream(self.session, hls_url)
def _get_streams(self): res = self.session.http.get(self.url) match = _playlist_url_re.search(res.text) if match is None: return res = self.session.http.get(match.group(1) + RUURL) sources = self.session.http.json(res, schema=_playlist_schema) streams = {} for source in sources: if source["type"] == "rtmp": streams["rtmp_live"] = RTMPStream(self.session, { "rtmp": source["streamer"], "pageUrl": self.url, "live": True }) elif source["type"] == "hls": streams.update( HLSStream.parse_variant_playlist(self.session, source["file"])) return streams
def _get_streams(self): match = _url_re.match(self.url) page = match.group("page") channel = match.group("channel") http.headers.update({'User-Agent': useragents.CHROME}) if page == 'user': res = http.get(self.url) userid = _userid_re.search(res.text).group(1) api = http.post(API_URL, data={"targetUserID": userid}) data = http.json(api, schema=_user_api_schema) rid = data["liveStreamID"] if rid == 0: self.logger.info("Stream currently unavailable.") return url = ROOM_URL.format(rid) res = http.get(url) elif page == 'profile': api = http.post(API_URL, data={"targetUserID": channel}) data = http.json(api, schema=_user_api_schema) rid = data["liveStreamID"] if rid == 0: self.logger.info("Stream currently unavailable.") return url = ROOM_URL.format(rid) res = http.get(url) else: res = http.get(self.url) status = _status_re.search(res.text) if not status: return if status.group(1) != 'true': self.logger.info("Stream currently unavailable.") return url = _rtmp_re.search(res.text).group(1) if 'rtmp:' in url: stream = RTMPStream(self.session, { "rtmp": url, "live": True }) yield "live", stream else: yield "live", HTTPStream(self.session, url) if '17app.co' in url: prefix = url.replace("rtmp:", "http:").replace(".flv", "/playlist.m3u8") if '/playlist.m3u8' not in prefix: url = prefix + "/playlist.m3u8" else: url = prefix for stream in HLSStream.parse_variant_playlist(self.session, url).items(): yield stream else: url = url.replace(".flv", ".m3u8") yield "live", HLSStream(self.session, url)
def _get_rtmp_stream(self, broadcast): info = self._get_stream_info(broadcast, "rtmp") if "view_url" in info: params = dict(rtmp=info["view_url"]) return RTMPStream(self.session, params=params, redirect=True)
def _get_rtmp_stream(self, stream_info): rtmp_url = '/'.join((stream_info['url'], stream_info['stream_name'])) quality = _rtmp_quality_lookup.get(stream_info['label'], "other") params = dict(rtmp=rtmp_url, live=True) return quality, RTMPStream(self.session, params=params)
def _get_streams(self): match = _url_re.match(self.url) subdomain = match.group("subdomain") http.verify = False http.mount('https://', HTTPAdapter(max_retries=99)) if subdomain == 'v': vid = match.group("vid") headers = { "User-Agent": useragents.ANDROID, "X-Requested-With": "XMLHttpRequest" } res = http.get(VAPI_URL.format(vid), headers=headers) room = http.json(res, schema=_vapi_schema) yield "source", HLSStream(self.session, room["video_url"]) return channel = match.group("channel") try: channel = int(channel) except ValueError: channel = http.get(self.url, schema=_room_id_schema) if channel is None: channel = http.get(self.url, schema=_room_id_alt_schema) http.headers.update({'User-Agent': useragents.ANDROID}) cdns = ["ws", "tct", "ws2", "dl"] ts = int(time.time()) suffix = "room/{0}?aid=androidhd1&cdn={1}&client_sys=android&time={2}".format( channel, cdns[0], ts) sign = hashlib.md5((suffix + API_SECRET).encode()).hexdigest() res = http.get(API_URL.format(suffix, sign)) room = http.json(res, schema=_room_schema) if not room: self.logger.info("Not a valid room url.") return if room["show_status"] != SHOW_STATUS_ONLINE: self.logger.info("Stream currently unavailable.") return url = room["hls_url"] yield "source", HLSStream(self.session, url) url = "{room[rtmp_url]}/{room[rtmp_live]}".format(room=room) if 'rtmp:' in url: stream = RTMPStream(self.session, {"rtmp": url, "live": True}) yield "source", stream else: yield "source", HTTPStream(self.session, url) multi_streams = {"middle": "low", "middle2": "medium"} for name, url in room["rtmp_multi_bitrate"].items(): url = "{room[rtmp_url]}/{url}".format(room=room, url=url) name = multi_streams[name] if 'rtmp:' in url: stream = RTMPStream(self.session, {"rtmp": url, "live": True}) yield name, stream else: yield name, HTTPStream(self.session, url)
def _get_streams(self): res = http.get(self.url) match = _swf_player_re.search(res.text) if match is None: return swf_url = "http://vaughnlive.tv" + match.group(1) self.logger.debug("Using swf url: {0}", swf_url) swfres = http.get(swf_url) swfdata = swfdecompress(swfres.content).decode("latin1") player_version_m = re.search(r"0\.\d+\.\d+\.\d+", swfdata) info_url_domain_m = re.search(r"\w+\.vaughnsoft\.net", swfdata) info_url_path_m = re.search(r"/video/edge/[a-zA-Z0-9_]+-", swfdata) player_version = player_version_m and player_version_m.group(0) info_url_domain = info_url_domain_m and info_url_domain_m.group(0) info_url_path = info_url_path_m and info_url_path_m.group(0) if player_version and info_url_domain and info_url_path: self.logger.debug( "Found player_version={0}, info_url_domain={1}, info_url_path={2}", player_version, info_url_domain, info_url_path) match = _url_re.match(self.url) params = { "channel": match.group("channel").lower(), "domain": DOMAIN_MAP.get(match.group("domain"), match.group("domain")), "version": player_version, "ms": random.randint(0, 999), "random": random.random(), "site": info_url_domain, "path": info_url_path } info_url = INFO_URL.format(**params) self.logger.debug("Loading info url: {0}", INFO_URL.format(**params)) info = http.get(info_url, schema=_schema) if not info: self.logger.info("This stream is currently unavailable") return app = "live" self.logger.debug("Streaming server is: {0}", info["server"]) if info["server"].endswith(":1337"): app = "live-{0}".format(info["ingest"].lower()) stream = RTMPStream( self.session, { "rtmp": "rtmp://{0}/live".format(info["server"]), "app": "{0}?{1}".format(app, info["token"]), "swfVfy": swf_url, "pageUrl": self.url, "live": True, "playpath": "{domain}_{channel}".format(**params), }) return dict(live=stream) else: self.logger.info( "Found player_version={0}, info_url_domain={1}, info_url_path={2}", player_version, info_url_domain, info_url_path) if not player_version: self.logger.error("Could not detect player_version") if not info_url_domain: self.logger.error("Could not detect info_url_domain") if not info_url_path: self.logger.error("Could not detect info_url_path")
def _create_flash_stream(self, server, channel, token): params = { "rtmp": self.RTMP_URL.format(server=server), "playpath": self.RTMP_PLAYPATH.format(token=token, channel=channel) } return RTMPStream(self.session, params=params)
def _get_streams(self): match = url_re.match(self.url) stream_page_scheme = 'https' stream_page_domain = match.group(4) stream_page_path = match.group(5) country_code = CONST_DEFAULT_COUNTRY_CODE is_paid_show = False # create http session and set headers http_session = http http_session.headers.update(CONST_HEADERS) # get swf url and cookies r = http_session.get( urlunparse((stream_page_scheme, stream_page_domain, stream_page_path, '', '', ''))) # redirect to profile page means stream is offline if '/profile/' in r.url: raise NoStreamsError(self.url) if not r.ok: self.logger.debug("Status code for {}: {}", r.url, r.status_code) raise NoStreamsError(self.url) if len(http_session.cookies) == 0: raise PluginError("Can't get a cookies") if urlparse(r.url).netloc != stream_page_domain: # then redirected to regional subdomain country_code = urlparse(r.url).netloc.split('.')[0].lower() # time to set variables baseurl = urlunparse( (stream_page_scheme, urlparse(r.url).netloc, '', '', '', '')) amf_gateway_url = urljoin(baseurl, CONST_AMF_GATEWAY_LOCATION) stream_page_url = urljoin(baseurl, stream_page_path) match = swf_re.search(r.text) if match: swf_url = urljoin(baseurl, match.group()) self.logger.debug("swf url found: {}", swf_url) else: # most likely it means that country/region banned # can try use default swf-url swf_url = urljoin(baseurl, CONST_DEFAULT_SWF_LOCATION) self.logger.debug("swf url not found. Will try {}", swf_url) # create amf query amf_message = AMFMessage("svDirectAmf.getRoomData", "/1", [stream_page_path, is_paid_show]) amf_packet = AMFPacket(version=0) amf_packet.messages.append(amf_message) # send request and close http-session r = http_session.post(url=amf_gateway_url, params={CONST_AMF_GATEWAY_PARAM: country_code}, data=bytes(amf_packet.serialize())) http_session.close() if r.status_code != 200: raise PluginError("unexpected status code for {}: {}", r.url, r.status_code) amf_response = AMFPacket.deserialize(BytesIO(r.content)) if len(amf_response.messages ) != 1 or amf_response.messages[0].target_uri != "/1/onResult": raise PluginError("unexpected response from amf gate") stream_source_info = amf_msg_schema.validate( amf_response.messages[0].value) self.logger.debug("source stream info:\n{}", stream_source_info) stream_params = { "live": True, "realtime": True, "flashVer": CONST_FLASH_VER, "swfUrl": swf_url, "tcUrl": stream_source_info['localData']['NC_ConnUrl'], "rtmp": stream_source_info['localData']['NC_ConnUrl'], "pageUrl": stream_page_url, "playpath": "%s?uid=%s" % (''.join(('stream_', stream_page_path)), self._get_stream_uid(stream_source_info['userData']['username'])), "conn": [ "S:{0}".format(stream_source_info['userData']['username']), "S:{0}".format( stream_source_info['localData']['NC_AccessKey']), "B:0", "S:{0}".format(stream_source_info['localData']['dataKey']) ] } self.logger.debug("Stream params:\n{}", stream_params) stream = RTMPStream(self.session, stream_params) return {'live': stream}
def _get_streams(self): res = http.get(self.url) m = self.cam_name_re.search(res.text) cam_name = m and m.group("name") json_base = self.cam_data_schema.validate(res.text) cam_data = json_base["cam"][cam_name] self.logger.debug("Found cam for {0} - {1}", cam_data["group"], cam_data["title"]) is_live = (cam_data["liveon"] == "true" and cam_data["defaulttab"] == "live") # HLS data hls_domain = cam_data["html5_streamingdomain"] hls_playpath = cam_data["html5_streampath"] # RTMP data rtmp_playpath = "" if is_live: n = "live" rtmp_domain = cam_data["streamingdomain"] rtmp_path = cam_data["livestreamingpath"] rtmp_live = cam_data["liveon"] if rtmp_path: match = self.playpath_re.search(rtmp_path) rtmp_playpath = match.group("file") rtmp_url = rtmp_domain + match.group("folder") else: n = "vod" rtmp_domain = cam_data["archivedomain"] rtmp_path = cam_data["archivepath"] rtmp_live = cam_data["archiveon"] if rtmp_path: rtmp_playpath = rtmp_path rtmp_url = rtmp_domain # RTMP stream if rtmp_playpath: self.logger.debug("RTMP URL: {0}{1}", rtmp_url, rtmp_playpath) params = { "rtmp": rtmp_url, "playpath": rtmp_playpath, "pageUrl": self.url, "swfUrl": self.swf_url, "live": rtmp_live } yield n, RTMPStream(self.session, params) # HLS stream if hls_playpath and is_live: hls_url = hls_domain + hls_playpath hls_url = update_scheme(self.url, hls_url) self.logger.debug("HLS URL: {0}", hls_url) for s in HLSStream.parse_variant_playlist(self.session, hls_url).items(): yield s if not (rtmp_playpath or hls_playpath): self.logger.error( "This cam stream appears to be in offline or " "snapshot mode and not live stream can be played.") return
def _get_streams(self): res = http.get(self.url, headers={'User-Agent': useragents.ANDROID}) match = self._video_data_re.search(res.text) if match is None: print(colored("\n => Performer is OFFLINE <=", "yellow", "on_red")) print(colored("\n => END <= ", 'yellow', 'on_blue')) time.sleep(3) sys.exit() if match: try: hls_streams = HLSStream.parse_variant_playlist( self.session, match.group('hls_url'), headers={'Referer': self.url}) for s in hls_streams.items(): rtmp_video = self._flash_data_schema.validate( match.group('flash_data')) swf = rtmp_video['playerUrl'] flashvars = rtmp_video['flashVars'] rtmp_stream = RTMPStream( self.session, { 'rtmp': rtmp_video['flashVars']['videoAppUrl'], 'playpath': rtmp_video['flashVars']['videoPlayUrl'], 'swfUrl': rtmp_video['playerUrl'] }) vpu = flashvars['videoPlayUrl'] rname = vpu.split('-')[0] wcdn = vpu.split('-')[1] print( colored("\n => PLAY URL => {} <=\n", "yellow", "on_blue")).format(vpu) vau = flashvars['videoAppUrl'] print( colored(" => APP URL => {} <=\n", "yellow", "on_blue")).format(vau) timestamp = str(time.strftime("%d%m%Y-%H%M%S")) path = config.get('folders', 'output_folder_C4') fn = rname + '_C4_' + timestamp + '.flv' pf1 = (path + fn) rtmp = config.get('files', 'rtmpdump') print( colored(' => RTMP-24/7-REC => {} <=', 'yellow', 'on_red')).format(fn) print command = '{} -r"{}" -a"cam4-edge-live" -W"{}" --live -y"{}" -o"{}"'.format( rtmp, vau, swf, vpu, pf1) os.system(command) sys.exit() except Exception as e: if '404' in str(e): print( colored("\n => Performer is AWAY or PRIVATE <=", "yellow", "on_red")) print print(colored("\n => END <= ", 'yellow', 'on_blue')) time.sleep(3) sys.exit()
def _create_flash_stream(self, server, args): params = { "rtmp": self.RTMP_URL.format(server=server), "playpath": self.RTMP_PLAYPATH.format(**args) } return RTMPStream(self.session, params=params)
def _get_streams(self): log.debug('Version 2018-07-01') log.info('This is a custom plugin. ' 'For support visit https://github.com/back-to/plugins') log.info('only FREE content is available.') http.headers.update({'User-Agent': useragents.FIREFOX}) channel = self._url_re.match(self.url).group('channel') log.info('Channel: {0}'.format(channel)) res = http.get(self.url_id.format(channel)) m = self._channel_id_re.search(res.text) if not m: raise PluginError('Invalid channel name, can\'t find channel id.') channel_id = m.group('id') data = (b'\x00\x00\x00\x00\x00\x01\x00\x10remoting.doEvent\x00\x02/1' + b'\x00\x00\x00;\n\x00\x00\x00\x02\x02\x00\n' + b'getChannel\x03\x00\x0bperformerID\x02\x00\x08' + channel_id.encode('ascii') + b'\x00\x04type\x02\x00\x04free\x00\x00\x09') res = http.post( self.url_gateway, headers={ 'Content-Type': 'application/x-amf', 'Referer': self.url_swf, }, data=data, ) data = AMFPacket.deserialize(BytesIO(res.content)) result = data.messages[0].value log.debug('--- DEBUG DATA ---'.format()) for _r in result: log.debug('{0}: {1}'.format(_r, result[_r])) log.debug('--- DEBUG DATA ---'.format()) if result['result'] != 'true': _err = self.error_code.get(str(int(result['errorCode']))) if _err: raise PluginError(_err) else: raise PluginError('Unknown error_code') channel_seq = result['channelSeq'] host = random.choice(result['freeServerIP'].split(',')) app = 'video_chat3_free_dx/{0}'.format(channel_seq) conn = [ 'O:1', 'NS:channel:{0}'.format(channel_id, result['channelID']), 'NS:pServer:{0}'.format(result['serverIP']), 'NS:langID:en', 'NS:channelSeq:{0}'.format(result['channelSeq']), 'O:O', ] params = { 'app': app, 'flashVer': 'WIN 29,0,0,171', 'swfVfy': self.url_swf, 'rtmp': 'rtmp://{0}/{1}'.format(host, app), 'live': True, 'pageUrl': self.url, 'playpath': 'free_performer', 'conn': conn } yield 'live', RTMPStream(self.session, params)
def _get_streams(self): """ Find all the streams for the ITV url :return: Mapping of quality to stream """ soap_message = self._soap_request() headers = {'Content-Length': '{0:d}'.format(len(soap_message)), 'Content-Type': 'text/xml; charset=utf-8', 'Host': 'secure-mercury.itv.com', 'Origin': 'http://www.itv.com', 'Referer': 'http://www.itv.com/Mercury/Mercury_VideoPlayer.swf?v=null', 'SOAPAction': "http://tempuri.org/PlaylistService/GetPlaylist", 'User-Agent': ITV_PLAYER_USER_AGENT, "X-Requested-With": "ShockwaveFlash/16.0.0.305"} res = http.post("https://secure-mercury.itv.com/PlaylistService.svc?wsdl", headers=headers, data=soap_message) # Parse XML xmldoc = http.xml(res) # Check that geo region has been accepted faultcode = xmldoc.find('.//faultcode') if faultcode is not None: if 'InvalidGeoRegion' in faultcode.text: self.logger.error('Failed to retrieve playlist data ' '(invalid geo region)') return None # Look for <MediaFiles> tag (RTMP streams) mediafiles = xmldoc.find('.//VideoEntries//MediaFiles') # Look for <ManifestFile> tag (HDS streams) manifestfile = xmldoc.find('.//VideoEntries//ManifestFile') # No streams if not mediafiles and not manifestfile: return None streams = {} # Proxy not needed for media retrieval (Note: probably better to use flag) # for x in ('http', 'https'): # if x in http.proxies: # http.proxies.pop(x); # Parse RTMP streams if mediafiles: rtmp = mediafiles.attrib['base'] for mediafile in mediafiles.findall("MediaFile"): playpath = mediafile.find("URL").text rtmp_url = urlparse(rtmp) app = (rtmp_url.path[1:] + '?' + rtmp_url.query).rstrip('?') live = app == "live" params = dict(rtmp="{u.scheme}://{u.netloc}{u.path}".format(u=rtmp_url), app=app.rstrip('?'), playpath=playpath, swfVfy=LIVE_SWF_URL if live else ONDEMAND_SWF_URL, timeout=10) if live: params['live'] = True bitrate = int(mediafile.attrib['bitrate']) / 1000 quality = "{0:d}k".format(int(bitrate)) streams[quality] = RTMPStream(self.session, params) # Parse HDS streams if manifestfile: url = manifestfile.find('URL').text if urlparse(url).path.endswith('f4m'): streams.update( HDSStream.parse_manifest(self.session, url, pvswf=LIVE_SWF_URL) ) return streams