def _get_streams(self): res = self.session.http.get(self.url) m = self.epg_re.search(res.text) channel_id = m and m.group(1) if channel_id: log.debug("Channel ID: {0}".format(channel_id)) if channel_id == "332": # there is a special backup stream for channel 332 bk_res = self.session.http.get(self.backup_332_api) bk_data = self.session.http.json(bk_res) if bk_data and bk_data["backup"]: log.info("Using backup stream for channel 332") return HLSStream.parse_variant_playlist(self.session, self.backup_332_stream) api_res = self.session.http.post(self.api_url, headers={"Content-Type": 'application/json'}, data=json.dumps(dict(channelno=channel_id, mode="prod", audioCode="", format="HLS", callerReferenceNo="20140702122500"))) data = self.session.http.json(api_res) for stream_url in data.get("asset", {}).get("hls", {}).get("adaptive", []): return HLSStream.parse_variant_playlist(self.session, stream_url)
def _get_streams(self): api = self._create_api() media_id = int(self.match.group("media_id")) try: # the media.stream_data field is required, no stream data is returned otherwise info = api.get_info(media_id, fields=[ "media.name", "media.series_name", "media.media_type", "media.stream_data" ], schema=_media_schema) except CrunchyrollAPIError as err: raise PluginError(f"Media lookup error: {err.msg}") if not info: return streams = {} self.title = info.get("name") self.author = info.get("series_name") self.category = info.get("media_type") info = info["stream_data"] # The adaptive quality stream sometimes a subset of all the other streams listed, ultra is no included has_adaptive = any( [s["quality"] == "adaptive" for s in info["streams"]]) if has_adaptive: log.debug("Loading streams from adaptive playlist") for stream in filter(lambda x: x["quality"] == "adaptive", info["streams"]): for q, s in HLSStream.parse_variant_playlist( self.session, stream["url"]).items(): # rename the bitrates to low, mid, or high. ultra doesn't seem to appear in the adaptive streams name = STREAM_NAMES.get(q, q) streams[name] = s # If there is no adaptive quality stream then parse each individual result for stream in info["streams"]: if stream["quality"] != "adaptive": # the video_encode_id indicates that the stream is not a variant playlist if "video_encode_id" in stream: streams[stream["quality"]] = HLSStream( self.session, stream["url"]) else: # otherwise the stream url is actually a list of stream qualities for q, s in HLSStream.parse_variant_playlist( self.session, stream["url"]).items(): # rename the bitrates to low, mid, or high. ultra doesn't seem to appear in the adaptive streams name = STREAM_NAMES.get(q, q) streams[name] = s return streams
def _get_streams(self): live_url = self._get_live_url() if not live_url: log.info("This stream may be off-air or not available in your country") return if self._is_token_based_site(): token = self._get_token() if not token: return return HLSStream.parse_variant_playlist(self.session, update_qsd(live_url, {"iut": token})) else: return HLSStream.parse_variant_playlist(self.session, live_url)
def _get_streams(self): api_urls = self.session.http.get(self.url, schema=self.channel_id_schema) _api_url = list(api_urls)[0] log.debug("API URL: {0}".format(_api_url)) player_api_url = self.session.http.get(_api_url, schema=self.player_api_schema) for api_url in player_api_url: log.debug("Player API URL: {0}".format(api_url)) for source in self.session.http.get(api_url, schema=self.stream_schema): log.debug("Stream source: {0} ({1})".format( source['src'], source.get("type", "n/a"))) if "type" not in source or source[ "type"] == "application/vnd.apple.mpegurl": streams = HLSStream.parse_variant_playlist( self.session, source["src"]) if not streams: yield "live", HLSStream(self.session, source["src"]) else: yield from streams.items() elif source["type"] == "application/dash+xml": yield from DASHStream.parse_manifest( self.session, source["src"]).items()
def _get_streams(self): try: self._login() except Exception as e: raise PluginError("SPWN login failed") from e m = self._URL_RE.match(self.url) eid = m.group("eid") event_info = self._get_event_data(eid) self.title = event_info.get("title", eid) log.info(f"Found SPWN event: {self.title}") stream_info = self._get_streaming_key(eid) if stream_info.get("isError"): raise PluginError("Error fetching stream info from SPWN API") cookies = stream_info.get("cookies") if not cookies: if not stream_info.get("hasTickets"): log.error("You do not have a ticket for this event") return msg = stream_info.get("msg", "") log.info(f"No available stream for this event: {msg}") return video_id = stream_info.get("videoIds", []).pop() info = cookies.get(video_id, {}).get("default", {}) for k, v in info.get("cookie", {}).items(): cookie = requests.cookies.create_cookie(k, v) self.session.http.cookies.set_cookie(cookie) url = info.get("url") if not url: raise PluginError(f"No stream URL for {video_id}") return HLSStream.parse_variant_playlist(self.session, url)
def _get_vod(self, root): schema_vod = validate.Schema( validate.xml_xpath_string( ".//script[@type='application/ld+json'][contains(text(),'VideoObject')][1]/text()" ), str, validate.transform( lambda jsonlike: re.sub(r"[\r\n]+", "", jsonlike)), validate.parse_json(), validate.any( validate.all( {"@graph": [dict]}, validate.get("@graph"), validate.filter(lambda obj: obj["@type"] == "VideoObject"), validate.get(0)), dict), {"contentUrl": validate.url()}, validate.get("contentUrl"), validate.transform( lambda content_url: update_scheme("https://", content_url))) try: vod = schema_vod.validate(root) except PluginError: return if urlparse(vod).path.endswith(".m3u8"): return HLSStream.parse_variant_playlist(self.session, vod) return {"vod": HTTPStream(self.session, vod)}
def _get_streams(self): hls_url = self.session.http.get(self.url, schema=validate.Schema( validate.transform(self._re_hls.search), validate.any(None, validate.get("hls_url")) )) if hls_url is not None: return HLSStream.parse_variant_playlist(self.session, hls_url)
def _get_streams_live(self): log.debug("Getting live HLS streams for {0}".format(self.channel)) try: data = json.dumps({ "query": """query {{ userByDisplayName(displayname:"{displayname}") {{ livestream {{ title }} username }} }}""".format(displayname=self.channel) }) res = self.session.http.post("https://graphigo.prd.dlive.tv/", data=data) res = self.session.http.json(res, schema=self._schema_userByDisplayName) if res["livestream"] is None: return except PluginError: return self.author = self.channel self.title = res["livestream"]["title"] hls_url = "https://live.prd.dlive.tv/hls/live/{0}.m3u8".format( res["username"]) return HLSStream.parse_variant_playlist(self.session, hls_url)
def _get_streams(self): video_id = self.session.http.get(self.url, schema=self.json_data_schema) if video_id is None: return log.debug('API ID: {0}'.format(video_id)) api_url = self.api_url.format(video_id) stream = self.session.http.get(api_url, schema=self.api_schema) log.trace('{0!r}'.format(stream)) if stream['type'].lower() != 'live': log.error('Invalid stream type "{0}"'.format(stream['type'])) return json_post_data = { 'requestorId': 'nbcnews', 'pid': video_id, 'application': 'NBCSports', 'version': 'v1', 'platform': 'desktop', 'token': '', 'resourceId': '', 'inPath': 'false', 'authenticationType': 'unauth', 'cdn': 'akamai', 'url': stream['sourceUrl'], } url = self.session.http.post( self.token_url, json=json_post_data, schema=self.token_schema, ) return HLSStream.parse_variant_playlist(self.session, url)
def mediaselector(self, vpid): urls = defaultdict(set) for platform in self.platforms: url = self.api_url.format(vpid=vpid, vpid_hash=self._hash_vpid(vpid), platform=platform) log.debug(f"Info API request: {url}") medias = self.session.http.get(url, schema=self.mediaselector_schema) for media in medias: for connection in media["connection"]: urls[connection.get("transferFormat")].add( connection["href"]) for stream_type, urls in urls.items(): log.debug(f"{len(urls)} {stream_type} streams") for url in list(urls): try: if stream_type == "hls": yield from HLSStream.parse_variant_playlist( self.session, url).items() if stream_type == "dash": yield from DASHStream.parse_manifest( self.session, url).items() log.debug(f" OK: {url}") except Exception: log.debug(f" FAIL: {url}")
def _get_streams(self): root = self.session.http.get(self.url, schema=validate.Schema( validate.parse_html())) # https://www.ntv.com.tr/canli-yayin/ntv?youtube=true yt_iframe = root.xpath( "string(.//iframe[contains(@src,'youtube.com')][1]/@src)") # https://www.startv.com.tr/canli-yayin dm_iframe = root.xpath( "string(.//iframe[contains(@src,'dailymotion.com')][1]/@src)") # https://www.kralmuzik.com.tr/tv/kral-tv # https://www.kralmuzik.com.tr/tv/kral-pop-tv yt_script = root.xpath( "string(.//script[contains(text(), 'youtube.init')][1]/text())") if yt_script: m = self._re_yt_script.search(yt_script) if m: yt_iframe = "https://www.youtube.com/watch?v={0}".format( m.group(1)) iframe = yt_iframe or dm_iframe if iframe: return self.session.streams(iframe) # http://eurostartv.com.tr/canli-izle dd_script = root.xpath( "string(.//script[contains(text(), '/live/hls/')][1]/text())") if dd_script: m = self._re_live_hls.search(dd_script) if m: return HLSStream.parse_variant_playlist( self.session, m.group(1))
def _get_streams(self): self.video_id = self.url.rsplit('/', 1)[-1] if self.get_option("email") and self.get_option("password"): self.login(self.get_option("email"), self.get_option("password")) mdata = self._get_movie_data() if mdata: log.debug("Found video: {0} ({1})".format(mdata["title"], mdata["id"])) m3u8_file = None # streaming if mdata["onair_status"] == 1: m3u8_file = mdata["media"]["url_ull"] # archive elif mdata["onair_status"] == 2 and mdata["media"][ "url_public"] is not None: m3u8_file = mdata["media"]["url_public"].replace( "public.m3u8", "playlist.m3u8") # uploaded video elif mdata["onair_status"] is None and mdata["movie_type"] == "2": m3u8_file = mdata["media"]["url"] else: log.error("There is no video file.") if m3u8_file is not None: yield from HLSStream.parse_variant_playlist( self.session, m3u8_file).items() else: log.error("You don't have the authority or no video file.")
def _get_streams(self): if not self.login(self.get_option("email"), self.get_option("password")): raise PluginError("Login failed") try: start_point = int( float( dict(parse_qsl(urlparse(self.url).query)).get( "startPoint", 0.0))) if start_point > 0: log.info("Stream will start at {0}".format( seconds_to_hhmmss(start_point))) except ValueError: start_point = 0 content_id = self._get_video_id() if content_id: log.debug("Found content ID: {0}".format(content_id)) info = self._get_media_info(content_id) if info.get("hlsUrl"): yield from HLSStream.parse_variant_playlist( self.session, info["hlsUrl"], start_offset=start_point).items() else: log.error("Could not find the HLS URL")
def get_live(self, live_slug): live_data = self.session.http.get( "https://aloula.faulio.com/api/v1/channels", schema=validate.Schema( validate.parse_json(), [{ "id": int, "url": str, "title": str, "has_live": bool, "has_vod": bool, "streams": { "hls": validate.url(), }, }], validate.filter(lambda k: k["url"] == live_slug), ), ) if not live_data: return live_data = live_data[0] log.trace(f"{live_data!r}") if not live_data["has_live"]: log.error("Stream is not live") return self.id = live_data["id"] self.author = "SBA" self.title = live_data["title"] self.category = "Live" return HLSStream.parse_variant_playlist(self.session, live_data["streams"]["hls"])
def _get_vod(self, user_id, video_name): res = self.session.http.get(urljoin(self.api_url, "getVideoByFileName"), params=dict(userId=user_id, videoName=video_name, serverType="web", callback="x")) vod_data = self.session.http.json(res, schema=self.vod_schema) if video_name == vod_data['ShowTitle']: host, base_path = self.server_addr_re.search( vod_data['ServerAddress']).groups() if not host or not base_path: raise PluginError("Could not split 'ServerAddress' components") base_file, file_ext = self.media_file_re.search( vod_data['MediaFile']).groups() if not base_file or not file_ext: raise PluginError("Could not split 'MediaFile' components") media_path = "{0}{1}{2}{3}{4}{5}".format( base_path, vod_data['MediaRoot'], base_file, vod_data['Bitrates'], file_ext, vod_data['StreamingType']) log.debug("Media path={0}".format(media_path)) vod_url = urlunparse((vod_data['ProtocolType'], host, media_path, '', vod_data['Token'], '')) log.debug("URL={0}".format(vod_url)) return HLSStream.parse_variant_playlist(self.session, vod_url)
def _get_streams(self): res = self.session.http.get(self.url) match = self._video_id_re.search( res.text) or self._video_id_alt_re.search(res.text) if match is None: return broadcaster_id = match.group('broadcaster_id') video_type = match.group('video_type') video_id = match.group('video_id') videos = self.session.http.get(self.DACAST_API_URL.format( broadcaster_id, video_type, video_id), schema=self._api_schema) token = self.session.http.get(self.DACAST_TOKEN_URL.format( broadcaster_id, video_type, video_id), schema=self._token_schema, headers={'referer': self.url}) parsed = [] for video_url in videos: video_url += token # Ignore duplicate video URLs if video_url in parsed: continue parsed.append(video_url) # Ignore HDS streams (broken) if '.m3u8' in video_url: yield from HLSStream.parse_variant_playlist( self.session, video_url).items()
def _get_streams(self): m = self.match if m: channel = m.group(1) or m.group(2) log.debug("Found channel {0}".format(channel)) for sformat, url in self.get_stream_urls(channel): try: if sformat == "dash": yield from DASHStream.parse_manifest( self.session, url, headers={ "User-Agent": useragents.CHROME }).items() if sformat == "hls": yield from HLSStream.parse_variant_playlist( self.session, url, headers={ "User-Agent": useragents.IPHONE }, ).items() except PluginError as e: log.error("Could not open {0} stream".format(sformat)) log.debug("Failed with error: {0}".format(e))
def _get_streams(self): res = self.session.http.get(self.url) match = self.playervars_re.search(res.text) if match: stream_url = match.group(2) log.debug("URL={0}".format(stream_url)) return HLSStream.parse_variant_playlist(self.session, stream_url)
def _get_streams(self): """ Find the streams for web.tv :return: """ headers = {} res = self.session.http.get(self.url, headers=headers) headers["Referer"] = self.url sources = self._sources_re.findall(res.text) if len(sources): sdata = parse_json(sources[0], schema=self._sources_schema) for source in sdata: log.debug(f"Found stream of type: {source['type']}") if source["type"] == "application/vnd.apple.mpegurl": url = update_scheme("https://", source["src"], force=False) try: # try to parse the stream as a variant playlist variant = HLSStream.parse_variant_playlist( self.session, url, headers=headers) if variant: yield from variant.items() else: # and if that fails, try it as a plain HLS stream yield 'live', HLSStream(self.session, url, headers=headers) except OSError: log.warning( "Could not open the stream, perhaps the channel is offline" )
def _get_streams(self): self.api = OnePlusOneAPI(self.session, self.url) url_hls = self.api.get_hls_url() if not url_hls: return for q, s in HLSStream.parse_variant_playlist(self.session, url_hls).items(): yield q, OnePlusOneHLS(self.session, s.url, self_url=self.url)
def _get_streams(self): # Construct manifest URL for this program. program_type, program_id = self.match.groups() manifest_type = self._program_type_map.get(program_type) if manifest_type is None: log.error(f"Unknown program type '{program_type}'") return None # Fetch program_id. res = self.session.http.get(self.url) m = self._program_id_re.search(res.text) if m is not None: program_id = m.group(1) elif program_id is None: log.error("Could not extract program ID from URL") return None manifest_url = urljoin( self._psapi_url, f"playback/manifest/{manifest_type}/{program_id}") # Extract media URL. res = self.session.http.get(manifest_url) manifest = self.session.http.json(res, schema=self._playable_schema) if 'nonPlayable' in manifest: reason = manifest["nonPlayable"]["reason"] log.error(f"Not playable ({reason})") return None self._set_metadata(manifest) asset = manifest['playable']['assets'][0] # Some streams such as podcasts are not HLS but plain files. if asset['format'] == 'HLS': return HLSStream.parse_variant_playlist(self.session, asset['url']) else: return [("live", HTTPStream(self.session, asset['url']))]
def _get_streams(self): player_js = self.session.http.get( self.url, schema=validate.Schema( validate.transform(self._re_player.search), validate.any( None, validate.Schema( validate.get(1), validate.transform( lambda url: update_scheme("https:", url)))))) if not player_js: return log.debug(f"Found player js {player_js}") data = self.session.http.get( player_js, schema=validate.Schema( validate.transform(self._re_json.match), validate.get(1), validate.parse_json(), validate.get("mediaResource"), validate.get("dflt"), { validate.optional("audioURL"): validate.url(), validate.optional("videoURL"): validate.url() })) if data.get("videoURL"): yield from HLSStream.parse_variant_playlist( self.session, update_scheme("https:", data.get("videoURL"))).items() if data.get("audioURL"): yield "audio", HTTPStream( self.session, update_scheme("https:", data.get("audioURL")))
def _get_streams(self): postdata = { "clientID": self.match.group(1), "showEncoder": True, "showMediaAssets": True, "showStreams": True, "includePrivate": False, "advancedDetails": True, "VAST": True, "eventID": self.match.group(2) } headers = { "Content-Type": "application/json", "wsc-api-key": self.WSC_API_KEY, "Authorization": "embedder" } res = self.session.http.post(self.API_URL, data=json.dumps(postdata), headers=headers) api_response = self.session.http.json(res, schema=self.api_response_schema) if api_response is None: return hls_url = api_response["data"]["streamingURIs"]["main"] return HLSStream.parse_variant_playlist( self.session, update_scheme("https://", hls_url))
def _get_streams_api(self, video_id): log.debug("Found video ID: {0}".format(video_id)) tld = self.match.group("tld") try: data = self.session.http.get( self._api.get(tld, "lt"), params=dict(video_id=video_id), schema=validate.Schema( validate.parse_json(), { "success": True, "data": { "versions": { validate.text: validate.all( [{ "type": validate.text, "src": validate.text, }], validate.filter(lambda item: item["type"] == "application/x-mpegurl") ) } } }, validate.get(("data", "versions")) ) ) except PluginError: log.error("Failed to get streams from API") return for stream in itertools.chain(*data.values()): src = update_scheme("https://", stream["src"], force=False) for s in HLSStream.parse_variant_playlist(self.session, src).items(): yield s
def _get_streams(self): api_url = self.session.http.get(self.url, schema=self._data_content_schema) if api_url and (api_url.startswith("/") or api_url.startswith("http")): api_url = urljoin(self.url, api_url) stream_url = self.session.http.get(api_url, schema=self._api_schema, headers={"Referer": self.url}) elif api_url and api_url.startswith("[{"): stream_url = self._api_schema.validate(api_url) else: if api_url is not None: log.error( "_data_content_schema returns invalid data: {0}".format( api_url)) return parsed = urlparse(stream_url) api_url = urljoin( self.url, self._token_api_path.format(url=stream_url, netloc="{0}://{1}".format( parsed.scheme, parsed.netloc), time=int(time()))) stream_url = self.session.http.get(api_url, schema=self._stream_schema, headers={"Referer": self.url}) return HLSStream.parse_variant_playlist(self.session, stream_url)
def _get_streams_delfi(self, src): try: data = self.session.http.get(src, schema=validate.Schema( validate.parse_html(), validate.xml_xpath_string(".//script[contains(text(),'embedJs.setAttribute(')][1]/text()"), validate.any(None, validate.all( validate.text, validate.transform(re.compile(r"embedJs\.setAttribute\('src',\s*'(.+?)'").search), validate.any(None, validate.all( validate.get(1), validate.transform(lambda url: parse_qsd(urlparse(url).fragment)), {"stream": validate.text}, validate.get("stream"), validate.parse_json(), {"versions": [{ "hls": validate.text }]}, validate.get("versions") )) )) )) except PluginError: log.error("Failed to get streams from iframe") return for stream in data: src = update_scheme("https://", stream["hls"], force=False) for s in HLSStream.parse_variant_playlist(self.session, src).items(): yield s
def _get_streams(self): res = self.session.http.get(self.url) m = self._re_channel_id.search(res.text) if not m: return res = self.session.http.get( "https://www.rtvs.sk/json/live5f.json", params={ "c": m.group(1), "b": "mozilla", "p": "win", "f": "0", "d": "1", } ) videos = parse_json(res.text, schema=validate.Schema({ "clip": { "sources": [{ "src": validate.url(), "type": str, }], }}, validate.get(("clip", "sources")), validate.filter(lambda n: n["type"] == "application/x-mpegurl"), )) for video in videos: yield from HLSStream.parse_variant_playlist(self.session, video["src"]).items()
def _get_streams(self): streams = self.session.http.get(self.url, schema=self._stream_schema) if streams is None: return if streams['type'] != 'STATION': return stream_urls = set() for stream in streams['streams']: log.trace('{0!r}'.format(stream)) url = stream['url'] url_no_scheme = urlunparse(urlparse(url)._replace(scheme='')) if url_no_scheme in stream_urls: continue stream_urls.add(url_no_scheme) if stream['contentFormat'] in ('audio/mpeg', 'audio/aac'): yield 'live', HTTPStream(self.session, url, allow_redirects=True) elif stream['contentFormat'] == 'video/MP2T': streams = HLSStream.parse_variant_playlist(self.session, stream["url"]) if not streams: yield stream["quality"], HLSStream(self.session, stream["url"]) else: for s in streams.items(): yield s
def _get_streams(self): nickname = self.match.group('nickname') res = self.session.http.get(f'https://wasd.tv/api/channels/nicknames/{nickname}') channel_id = self.session.http.json(res, schema=self._api_nicknames_schema) res = self.session.http.get( 'https://wasd.tv/api/v2/media-containers', params={ 'media_container_status': 'RUNNING', 'limit': '1', 'offset': '0', 'channel_id': channel_id, 'media_container_type': 'SINGLE,COOP', } ) json_res = self.session.http.json(res, schema=self._api_schema) log.trace('{0!r}'.format(json_res)) if not json_res: raise PluginError('No data returned from URL={0}'.format(res.url)) for stream in json_res['media_container_streams']: log.debug('media_container_status: {0}, media_container_online_status: {1}'.format( json_res['media_container_status'], json_res['media_container_online_status'])) for stream in stream['stream_media']: if stream['media_status'] == 'STOPPED': hls_url = stream['media_meta']['media_archive_url'] elif stream['media_status'] == 'RUNNING': hls_url = stream['media_meta']['media_url'] yield from HLSStream.parse_variant_playlist(self.session, hls_url).items()
def _get_streams(self): url = self.session.http.get( "https://stream.1tv.ru/api/playlist/1tvch_as_array.json", data={"r": random.randint(1, 100000)}, schema=validate.Schema( validate.parse_json(), {"hls": [validate.url()]}, validate.get("hls"), validate.get(0), )) if not url: return if "georestrictions" in url: log.error("Stream is geo-restricted") return hls_session = self.session.http.get( "https://stream.1tv.ru/get_hls_session", schema=validate.Schema( validate.parse_json(), {"s": validate.transform(unquote)}, )) url = update_qsd(url, qsd=hls_session, safe="/:") yield from HLSStream.parse_variant_playlist(self.session, url, name_fmt="{pixels}_{bitrate}").items()