def _get_streams(self): res = http.get(self.url) channel_id = self._find_channel_id(res.text) if not channel_id: return stream_id = self._get_stream_id(channel_id) if not stream_id: return res = http.get(STREAM_API_URL.format(stream_id), params=dict(format="all")) json = http.json(res) data = verifyjson(json, "data") items = verifyjson(data, "items") streams = {} for stream in filter(valid_stream, items): parser = STREAM_TYPES[stream["format"]] try: streams.update(parser(self.session, stream["url"])) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to extract {0} streams: {1}", stream["format"].upper(), err) return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") if not "live_playback" in args or args["live_playback"] == "0": raise NoStreamsError(self.url) streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"][0], params=dict(signature=streaminfo["sig"][0])) if streaminfo["itag"][0] in formatmap: quality = formatmap[streaminfo["itag"][0]] else: quality = streaminfo["quality"] streams[quality] = stream return streams
def _get_streams(self): self.logger.debug("Fetching stream info") info = self._get_stream_info() if not info: raise NoStreamsError(self.url) streaminfo = verifyjson(info, "stream_info") if not streaminfo: raise NoStreamsError(self.url) qualities = verifyjson(streaminfo, "qualities") streams = {} if not streaminfo["is_live"]: raise NoStreamsError(self.url) if "play_url" in streaminfo: smil = self._parse_smil(streaminfo["play_url"]) for bitrate, stream in smil.items(): sname = "{0}k".format(bitrate / 1000) for quality in qualities: if quality["bitrate"] == bitrate: sname = "{0}p".format(quality["height"]) streams[sname] = stream return streams
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url, params=dict(output="json")) if res.json is None: raise PluginError("No JSON data in stream info") streams = {} video = verifyjson(res.json, "video") videos = verifyjson(video, "videoReferences") for video in videos: if not ("url" in video and "playerType" in video): continue if video["playerType"] == "flash": if video["url"].startswith("rtmp"): stream = RTMPStream( self.session, { "rtmp": video["url"], "pageUrl": self.PageURL, "swfVfy": self.SWFURL, "live": True }) streams[str(video["bitrate"]) + "k"] = stream elif video["playerType"] == "ios": try: hlsstreams = HLSStream.parse_variant_playlist( self.session, video["url"]) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) return streams
def _get_live_streams(self): self._authenticate() sig, token = self._access_token() url = self.usher.select(self.channel, password=self.options.get("password"), nauthsig=sig, nauth=token) try: streams = HLSStream.parse_variant_playlist(self.session, url) except IOError as err: err = str(err) if "404 Client Error" in err or "Failed to parse playlist" in err: return else: raise PluginError(err) try: token = parse_json(token) chansub = verifyjson(token, "chansub") restricted_bitrates = verifyjson(chansub, "restricted_bitrates") for name in filter( lambda n: not re.match(r"(.+_)?archives|live", n), restricted_bitrates): self.logger.warning( "The quality '{0}' is not available " "since it requires a subscription.", name) except PluginError: pass return dict(starmap(self._check_stream_name, streams.items()))
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url, params=dict(output="json")) json = res_json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") streams = {} video = verifyjson(json, "video") videos = verifyjson(video, "videoReferences") for video in videos: if not ("url" in video and "playerType" in video): continue if video["playerType"] == "flash": if video["url"].startswith("rtmp"): stream = RTMPStream( self.session, {"rtmp": video["url"], "pageUrl": self.PageURL, "swfVfy": self.SWFURL, "live": True}, ) streams[str(video["bitrate"]) + "k"] = stream elif video["playerType"] == "ios": try: hlsstreams = HLSStream.parse_variant_playlist(self.session, video["url"]) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) return streams
def _get_live_streams(self): self._authenticate() sig, token = self._access_token() url = self.usher.select(self.channel, password=self.options.get("password"), nauthsig=sig, nauth=token) try: streams = HLSStream.parse_variant_playlist(self.session, url) except ValueError: return except IOError as err: if "404 Client Error" in str(err): return else: raise PluginError(err) try: token = parse_json(token) chansub = verifyjson(token, "chansub") restricted_bitrates = verifyjson(chansub, "restricted_bitrates") for name in filter(lambda n: n not in ("archives", "live"), restricted_bitrates): self.logger.warning("The quality '{0}' is not available " "since it requires a subscription.", name) except PluginError: pass return dict(starmap(self._check_stream_name, streams.items()))
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") if not "live_playback" in args or args["live_playback"] == "0": raise NoStreamsError(self.url) streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"][0], params=dict(signature=streaminfo["sig"][0])) if streaminfo["itag"][0] in formatmap: quality = formatmap[streaminfo["itag"][0]] else: quality = streaminfo["quality"] streams[quality] = stream return streams
def _get_streams(self): res = http.get(self.url) channel_id = self._find_channel_id(res.text) if not channel_id: return stream_id = self._get_stream_id(channel_id) if not stream_id: return res = http.get(STREAM_API_URL.format(stream_id), params=dict(format="all")) json = http.json(res) data = verifyjson(json, "data") items = verifyjson(data, "items") streams = {} for stream in filter(valid_stream, items): parser = STREAM_TYPES[stream["format"]] try: streams.update(parser(self.session, stream["url"])) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to extract {0} streams: {1}", stream["format"].upper(), err) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") info = self._get_stream_info() if not info: raise NoStreamsError(self.url) streaminfo = verifyjson(info, "stream_info") if not streaminfo: raise NoStreamsError(self.url) qualities = verifyjson(streaminfo, "qualities") streams = {} if not streaminfo["is_live"]: raise NoStreamsError(self.url) if "play_url" in streaminfo: smil = self._parse_smil(streaminfo["play_url"]) for bitrate, stream in smil.items(): sname = "{0}k".format(bitrate/1000) for quality in qualities: if quality["bitrate"] == bitrate: sname = "{0}p".format(quality["height"]) streams[sname] = stream return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if "s" in streaminfo and self._decrypt_signature(streaminfo["s"]): streaminfo["sig"] = self._decrypt_signature(streaminfo["s"]) if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"], params=dict(signature=streaminfo["sig"])) if streaminfo["itag"] in formatmap: quality = formatmap[streaminfo["itag"]] else: quality = streaminfo["quality"] if streaminfo.get("stereo3d") == "1": quality += "_3d" streams[quality] = stream if "hlsvp" in args: url = args["hlsvp"] try: hlsstreams = HLSStream.parse_variant_playlist(self.session, url, namekey="pixels") streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) if not streams and args.get("live_playback", "0") == "0": self.logger.warning( "VOD support may not be 100% complete. Try youtube-dl instead." ) return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if "s" in streaminfo and self._decrypt_signature(streaminfo["s"]): streaminfo["sig"] = self._decrypt_signature(streaminfo["s"]) if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"], params=dict(signature=streaminfo["sig"])) if streaminfo["itag"] in formatmap: quality = formatmap[streaminfo["itag"]] else: quality = streaminfo["quality"] if streaminfo.get("stereo3d") == "1": quality += "_3d" streams[quality] = stream if "hlsvp" in args: url = args["hlsvp"] try: hlsstreams = HLSStream.parse_variant_playlist(self.session, url, namekey="pixels") streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) if not streams and args.get("live_playback", "0") == "0": self.logger.warning("VOD support may not be 100% complete. Try youtube-dl instead.") return streams
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="any", connection="wifi"), exception=IOError) except IOError: self.logger.debug("HLS streams not available") return {} json = res_json(res, "stream token JSON") if not isinstance(json, list): raise PluginError("Invalid JSON response") if len(json) == 0: raise PluginError("No stream token in JSON") streams = {} token = verifyjson(json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true") playlist = HLSStream.parse_variant_playlist(self.session, url, params=params) except IOError as err: raise PluginError(err) return playlist
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="any", connection="wifi"), exception=IOError) except IOError: return {} if not isinstance(res.json, list): raise PluginError("Stream info response is not JSON") if len(res.json) == 0: raise PluginError("No stream token in JSON") streams = {} token = verifyjson(res.json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true") playlist = HLSStream.parse_variant_playlist(self.session, url, params=params) except IOError as err: raise PluginError(err) return playlist
def _get_streams_from_id(self, stream_id): res = urlget(CONFIG_URL, params=dict(id=stream_id)) config = res_json(res) media = verifyjson(config, "media") if not (media and isinstance(media, list)): return streams = {} media = media[0] hds_manifest = media.get("name") hls_manifest = media.get("hlsUrl") if hds_manifest: try: hds_streams = HDSStream.parse_manifest(self.session, hds_manifest) streams.update(hds_streams) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to parse HDS manifest: {0}", err) if hls_manifest: try: hls_streams = HLSStream.parse_variant_playlist(self.session, hls_manifest, nameprefix="mobile_") streams.update(hls_streams) except IOError as err: if not re.search(r"(404|400) Client Error", str(err)): self.logger.error("Failed to parse HLS playlist: {0}", 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): self.logger.debug("Fetching stream info") res = http.get(self.url, params=dict(output="json")) json = http.json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") streams = {} video = verifyjson(json, "video") videos = verifyjson(video, "videoReferences") for video in videos: if not ("url" in video and "playerType" in video): continue url = video["url"] if video["playerType"] == "flash": if url.startswith("rtmp"): stream = RTMPStream( self.session, { "rtmp": url, "pageUrl": PAGE_URL, "swfVfy": SWF_URL, "live": True }) streams[str(video["bitrate"]) + "k"] = stream elif "manifest.f4m" in url: try: hdsstreams = HDSStream.parse_manifest( self.session, url) streams.update(hdsstreams) except IOError as err: self.logger.warning("Failed to get HDS manifest: {0}", err) elif video["playerType"] == "ios": try: hlsstreams = HLSStream.parse_variant_playlist( self.session, url) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) return streams
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") if not "live_playback" in args or args["live_playback"] == "0": raise NoStreamsError(self.url) streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"], params=dict(signature=streaminfo["sig"])) if streaminfo["itag"] in formatmap: quality = formatmap[streaminfo["itag"]] else: quality = streaminfo["quality"] streams[quality] = stream if "hlsvp" in args: url = args["hlsvp"] try: hlsstreams = HLSStream.parse_variant_playlist( self.session, url) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) return streams
def _check_channel_live(self, channelname): url = self.MetadataURL.format(channelname) res = urlget(url, params=dict(fields="mode")) if len(res.json) == 0: raise PluginError("Error retrieving stream live status") mode = verifyjson(res.json, "mode") return mode == "live"
def _check_channel_live(self, channelname): url = self.MetadataURL.format(channelname) res = urlget(url, params=dict(fields="mode")) if len(res.json) == 0: raise PluginError("Error retrieving stream live status") mode = verifyjson(res.json, "mode") return mode == "live"
def _get_streams(self): info = self._get_stream_info(self.url) if not info: raise NoStreamsError(self.url) args = verifyjson(info, "args") if not "live_playback" in args or args["live_playback"] == "0": raise NoStreamsError(self.url) streams = {} uestreammap = verifyjson(args, "url_encoded_fmt_stream_map") fmtlist = verifyjson(args, "fmt_list") streammap = self._parse_stream_map(uestreammap) formatmap = self._parse_format_map(fmtlist) for streaminfo in streammap: if not ("url" in streaminfo and "sig" in streaminfo): continue stream = HTTPStream(self.session, streaminfo["url"], params=dict(signature=streaminfo["sig"])) if streaminfo["itag"] in formatmap: quality = formatmap[streaminfo["itag"]] else: quality = streaminfo["quality"] streams[quality] = stream if "hlsvp" in args: url = args["hlsvp"] try: hlsstreams = HLSStream.parse_variant_playlist(self.session, url) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", 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 _find_channel_config(self, data): match = re.search(r'meta itemprop="channelId" content="([^"]+)"', data) if not match: return channel_id = match.group(1) query = dict(channelId=channel_id, type="video", eventType="live", part="id", key=API_KEY) res = http.get(API_SEARCH_URL, params=query) res = http.json(res) videos = verifyjson(res, "items") for video in videos: info = verifyjson(video, "id") video_id = info.get("videoId") url = "http://youtube.com/watch?v={0}".format(video_id) config = self._get_stream_info(url) if config: return config
def _check_channel_live(self, channelname): url = self.MetadataURL.format(channelname) res = urlget(url, params=dict(fields="mode")) json = res_json(res) if not isinstance(json, dict): raise PluginError("Invalid JSON response") mode = verifyjson(json, "mode") return mode == "live"
def _get_stream_id(self, channel_id): res = http.get(CONFIG_API_URL, params=dict(id=channel_id)) config = http.json(res) media = verifyjson(config, "media") if not (media and isinstance(media, list)): return media = media[0] if not isinstance(media, dict): return return media.get("channel")
def _get_streams(self): self.logger.debug("Fetching stream info") info = self._get_stream_info() if not info: raise NoStreamsError(self.url) event = verifyjson(info, "event") streaminfo = verifyjson(event, "stream_info") if not streaminfo or not streaminfo.get("is_live"): raise NoStreamsError(self.url) streams = defaultdict(list) play_url = streaminfo.get("play_url") if play_url: swfurl = info.get("viewerPlusSwfUrl") or info.get("hdPlayerSwfUrl") if not swfurl.startswith("http"): swfurl = "http://" + swfurl qualities = streaminfo.get("qualities", []) smil = self._parse_smil(streaminfo["play_url"], swfurl) for bitrate, stream in smil.items(): name = "{0}k".format(bitrate/1000) for quality in qualities: if quality["bitrate"] == bitrate: name = "{0}p".format(quality["height"]) streams[name].append(stream) m3u8_url = streaminfo.get("m3u8_url") if m3u8_url: hls_streams = HLSStream.parse_variant_playlist(self.session, m3u8_url, namekey="pixels") for name, stream in hls_streams.items(): streams[name].append(stream) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") info = self._get_stream_info() if not info: raise NoStreamsError(self.url) event = verifyjson(info, "event") streaminfo = verifyjson(event, "stream_info") if not streaminfo or not streaminfo.get("is_live"): raise NoStreamsError(self.url) streams = defaultdict(list) play_url = streaminfo.get("play_url") if play_url: swfurl = info.get("viewerPlusSwfUrl") or info.get("hdPlayerSwfUrl") if not swfurl.startswith("http"): swfurl = "http://" + swfurl qualities = streaminfo.get("qualities", []) smil = self._parse_smil(streaminfo["play_url"], swfurl) for bitrate, stream in smil.items(): name = "{0}k".format(bitrate / 1000) for quality in qualities: if quality["bitrate"] == bitrate: name = "{0}p".format(quality["height"]) streams[name].append(stream) m3u8_url = streaminfo.get("m3u8_url") if m3u8_url: hls_streams = HLSStream.parse_variant_playlist(self.session, m3u8_url, namekey="pixels") for name, stream in hls_streams.items(): streams[name].append(stream) return streams
def _get_stream_id(self, channel_id): res = http.get(CONFIG_API_URL, params=dict(id=channel_id)) config = http.json(res) media = verifyjson(config, "media") if not (media and isinstance(media, list)): return media = media[0] if not isinstance(media, dict): return return media.get("channel")
def _get_streams(self): self.logger.debug("Fetching stream info") res = urlget(self.url, params=dict(output="json")) if res.json is None: raise PluginError("No JSON data in stream info") streams = {} video = verifyjson(res.json, "video") videos = verifyjson(video, "videoReferences") swfhash, swfsize = (None, None) for video in videos: if not ("url" in video and "playerType" in video): continue if video["playerType"] == "flash": if video["url"].startswith("rtmp"): if not swfhash: self.logger.debug("Verifying SWF: {0}", self.SWFURL) swfhash, swfsize = swfverify(self.SWFURL) stream = RTMPStream(self.session, { "rtmp": video["url"], "pageUrl": self.PageURL, "swfhash": swfhash, "swfsize": swfsize, "live": True }) streams[str(video["bitrate"]) + "k"] = stream elif video["playerType"] == "ios": try: hlsstreams = HLSStream.parse_variant_playlist(self.session, video["url"]) streams.update(hlsstreams) except IOError as err: self.logger.warning("Failed to get variant playlist: {0}", err) 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") data = urlget(self.JSONURL.format(channelid)) try: info = json.loads(str(data, "utf8")) except ValueError as err: raise PluginError(("Unable to parse JSON: {0})").format(err)) streams = {} video = verifyjson(info, "video") videos = verifyjson(video, "videoReferences") self.logger.debug("Verifying SWF: {0}", self.SWFURL) swfhash, swfsize = swfverify(self.SWFURL) for video in videos: if not ("url" in video and "playerType" in video and video["playerType"] == "flash"): continue stream = RTMPStream(self.session, { "rtmp": video["url"], "pageUrl": self.PageURL, "swfhash": swfhash, "swfsize": swfsize, "live": True }) streams[str(video["bitrate"]) + "k"] = stream return streams
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="iphone", connection="wifi", allow_cdn="true"), exception=IOError) except IOError: self.logger.debug("HLS streams not available") return {} json = res_json(res, "stream token JSON") if not isinstance(json, list): raise PluginError("Invalid JSON response") if len(json) == 0: raise PluginError("No stream token in JSON") token = verifyjson(json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true", allow_cdn="true") playlist = HLSStream.parse_variant_playlist(self.session, url, params=params) except IOError as err: if "404" in err: raise PluginError(err) else: self.logger.debug("Requesting mobile transcode") payload = dict(channel=self.channelname, type="iphone") urlopen("http://usher.twitch.tv/stream/transcode_iphone.json", data=payload) return {} return playlist
def create_playlist_token(self, channel): url = self.url(HLS_TOKEN_PATH, channel) params = dict(type="iphone", allow_cdn="true") try: res = urlget(url, params=params, exception=IOError) except IOError: return None json = res_json(res, "stream token JSON") if not (isinstance(json, list) and json): raise PluginError("Invalid JSON response") token = verifyjson(json[0], "token") hashed = hmac.new(HLS_TOKEN_KEY, bytes(token, "utf8"), sha1) return "{0}:{1}".format(hashed.hexdigest(), token)
def _get_hls_streams(self): url = self.HLSStreamTokenURL.format(self.channelname) try: res = urlget(url, params=dict(type="iphone", connection="wifi", allow_cdn="true"), exception=IOError) except IOError: self.logger.debug("HLS streams not available") return {} json = res_json(res, "stream token JSON") if not isinstance(json, list): raise PluginError("Invalid JSON response") if len(json) == 0: raise PluginError("No stream token in JSON") token = verifyjson(json[0], "token") hashed = hmac.new(self.HLSStreamTokenKey, bytes(token, "utf8"), sha1) fulltoken = hashed.hexdigest() + ":" + token url = self.HLSPlaylistURL.format(self.channelname) try: params = dict(token=fulltoken, hd="true", allow_cdn="true") playlist = HLSStream.parse_variant_playlist(self.session, url, nameprefix="mobile_", params=params) except IOError as err: if "404" not in str(err): raise PluginError(err) else: self.logger.debug("Requesting mobile transcode") payload = dict(channel=self.channelname, type="iphone") urlopen(self.HLSTranscodeRequest, data=payload) return {} return playlist
def _get_streams(self): match = re.match(URL_REGEX, self.url) if not match: return stream_id = match.group("stream_id") res = http.get(STREAM_API.format(stream_id)) json = http.json(res) stream_info = verifyjson(json, "streams") streams = {} swf_url = None for name, stream_url in stream_info.items(): stream_url = str(stream_url) if stream_url.endswith(".m3u8"): try: hls_streams = HLSStream.parse_variant_playlist(self.session, stream_url) streams.update(hls_streams) except IOError as err: self.logger.error("Failed to fetch HLS streams: {0}", err) elif stream_url.startswith("rtmp://"): swf_url = swf_url or self._get_swf_url() params = { "rtmp": stream_url, "pageUrl": self.url, "swfVfy": swf_url, } if stream_url.endswith(".mp4"): tcurl, playpath = rtmpparse(stream_url) params["rtmp"] = tcurl params["playpath"] = playpath else: params["live"] = True streams[name] = RTMPStream(self.session, params) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: return stream_name, media_id = match.groups() if stream_name != "video": res = http.get(LIVE_API.format(stream_name)) json = http.json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: return media_type = "live" if media_is_live else "video" res = http.get(PLAYER_API.format(media_type, media_id)) json = http.json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") plugins = verifyjson(json, "plugins") streams = {} if live: playlists = verifyjson(json, "playlist") or [] swf_url = SWF_URL for playlist in playlists: bitrates = playlist.get("bitrates") provider = playlist.get("connectionProvider") rtmp = None if bitrates: rtmp = playlist.get("netConnectionUrl") elif provider and provider in plugins: provider = plugins[provider] swf_name = verifyjson(provider, "url") swf_url = SWF_BASE + swf_name rtmp = verifyjson(provider, "netConnectionUrl") bitrates = clip.get("bitrates", []) else: continue for bitrate in bitrates: quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") stream = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": swf_url, "live": True }) if quality in streams: quality += "_alt" streams[quality] = stream else: bitrates = verifyjson(clip, "bitrates") for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: raise NoStreamsError(self.url) stream_name, media_id = match.groups() if stream_name != "video": res = urlget(LIVE_API.format(stream_name)) json = res_json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: raise NoStreamsError(self.url) media_type = "live" if media_is_live else "video" res = urlget(PLAYER_API.format(media_type, media_id)) json = res_json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") bitrates = verifyjson(clip, "bitrates") streams = {} if live: for bitrate in bitrates: connection_provider = clip.get("connectionProvider", "clustering") plugins = verifyjson(json, "plugins") provider_plugin = verifyjson(plugins, connection_provider) swf = verifyjson(provider_plugin, "url") rtmp = verifyjson(provider_plugin, "netConnectionUrl") quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") streams[quality] = RTMPStream( self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": SWF_BASE + swf, "live": True }) else: for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: return stream_name, media_id = match.groups() if stream_name != "video": res = http.get(LIVE_API.format(stream_name)) json = http.json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: return media_type = "live" if media_is_live else "video" res = http.get(PLAYER_API.format(media_type, media_id)) json = http.json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") streams = {} if live: playlists = verifyjson(json, "playlist") or [] for playlist in filter(valid_playlist, playlists): bitrates = playlist.get("bitrates") rtmp = playlist.get("netConnectionUrl") for bitrate in bitrates: quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") streams[quality] = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": SWF_URL, "live": True }) else: bitrates = verifyjson(clip, "bitrates") for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: raise NoStreamsError(self.url) stream_name, media_id = match.groups() if stream_name != "video": res = urlget(LIVE_API.format(stream_name)) json = res_json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: raise NoStreamsError(self.url) media_type = "live" if media_is_live else "video" res = urlget(PLAYER_API.format(media_type, media_id)) json = res_json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") bitrates = verifyjson(clip, "bitrates") streams = {} if live: for bitrate in bitrates: connection_provider = clip.get("connectionProvider", "clustering") plugins = verifyjson(json, "plugins") provider_plugin = verifyjson(plugins, connection_provider) swf = verifyjson(provider_plugin, "url") rtmp = verifyjson(provider_plugin, "netConnectionUrl") quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") streams[quality] = RTMPStream(self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": SWF_BASE + swf, "live": True }) else: for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams
def _get_streams(self): self.logger.debug("Fetching stream info") media_is_live = 0 match = re.search(r".*hitbox.tv/([^/]*)/?(\d+)?", self.url) if not match: return stream_name, media_id = match.groups() if stream_name != "video": res = http.get(LIVE_API.format(stream_name)) json = http.json(res) livestream = verifyjson(json, "livestream") media_id = verifyjson(livestream[0], "media_id") media_is_live = int(verifyjson(livestream[0], "media_is_live")) if not media_is_live: return media_type = "live" if media_is_live else "video" res = http.get(PLAYER_API.format(media_type, media_id)) json = http.json(res) clip = verifyjson(json, "clip") live = verifyjson(clip, "live") plugins = verifyjson(json, "plugins") streams = {} if live: playlists = verifyjson(json, "playlist") or [] swf_url = SWF_URL for playlist in playlists: bitrates = playlist.get("bitrates") provider = playlist.get("connectionProvider") rtmp = None if bitrates: rtmp = playlist.get("netConnectionUrl") elif provider and provider in plugins: provider = plugins[provider] swf_name = verifyjson(provider, "url") swf_url = SWF_BASE + swf_name rtmp = verifyjson(provider, "netConnectionUrl") bitrates = clip.get("bitrates", []) else: continue for bitrate in bitrates: quality = self._get_quality(verifyjson(bitrate, "label")) url = verifyjson(bitrate, "url") stream = RTMPStream( self.session, { "rtmp": rtmp, "pageUrl": self.url, "playpath": url, "swfVfy": swf_url, "live": True }) if quality in streams: quality += "_alt" streams[quality] = stream else: bitrates = verifyjson(clip, "bitrates") for bitrate in bitrates: base_url = verifyjson(clip, "baseUrl") url = verifyjson(bitrate, "url") quality = self._get_quality(verifyjson(bitrate, "label")) streams[quality] = HTTPStream(self.session, base_url + "/" + url) return streams