def get_media(url, options): stream = service_handler(url) if not stream: url, stream = Generic().get(url) url = url.replace("&", "&") if not stream: log.error("That site is not supported. Make a ticket or send a message") sys.exit(2) if not options.output or os.path.isdir(options.output): data = get_http_data(url) match = re.search("(?i)<title.*>\s*(.*?)\s*</title>", data) if match: if sys.version_info > (3, 0): title = re.sub('[^\w\s-]', '', match.group(1)).strip().lower() if options.output: options.output = options.output + re.sub('[-\s]+', '-', title) else: options.output = re.sub('[-\s]+', '-', title) else: title = unicode(re.sub('[^\w\s-]', '', match.group(1)).strip().lower()) if options.output: options.output = unicode(options.output + re.sub('[-\s]+', '-', title)) else: options.output = unicode(re.sub('[-\s]+', '-', title)) stream.get(options, url)
def find_all_episodes(self, options): match = re.search(r"data-franchise='([^']+)'", self.get_urldata()[1]) if match is None: log.error("Couldn't program id") return programid = match.group(1) match = re.findall(r"<li class='(divider playlist-item|playlist-item)'( data-item-id='([^']+)')?", self.get_urldata()[1]) if not match: log.error("Couldn't retrieve episode list") return episodNr = [] for i in match: if i[0] == "playlist-item": episodNr.append(i[2]) else: break episodes = [] n = 0 for i in sorted(episodNr): if n == options.all_last: break episodes.append("http://www.nickelodeon.se/serier/%s-something/videos/%s-something" % (programid, i)) n += 1 return episodes
def find_all_episodes(self, options): data = self.get_urldata() parse = urlparse(self.url) domain = re.search(r"(dplay\.\w\w)", parse.netloc).group(1) match = re.search('data-show-id="([^"]+)"', data) if not match: log.error("Cant find show id") return None premium = None if options.username and options.password: premium = self._login(options) url = "http://www.%s/api/v2/ajax/shows/%s/seasons/?items=9999999&sort=episode_number_desc&page=" % (domain, match.group(1)) episodes = [] page = 0 data = self.http.request("get", "%s%s" % (url, page)).text dataj = json.loads(data) for i in dataj["data"]: what = self._playable(dataj, premium) if what == 0: episodes.append(i["url"]) pages = dataj["total_pages"] for n in range(1, pages): data = self.http.request("get", "%s%s" % (url, n)).text dataj = json.loads(data) for i in dataj["data"]: what = self._playable(dataj, premium) if what == 0: episodes.append(i["url"]) if len(episodes) == 0: log.error("Cant find any playable files") if options.all_last > 0: return episodes[:options.all_last] return episodes
def get(self, options): parse = urlparse(self.url) try: other = parse.fragment except KeyError: log.error("Something wrong with that url") sys.exit(2) match = re.search("^/(.*).html", other) if not match: log.error("Cant find video file") sys.exit(2) url = "http://www.hbo.com/data/content/%s.xml" % match.group(1) data = get_http_data(url) xml = ET.XML(data) videoid = xml.find("content")[1].find("videoId").text url = "http://render.cdn.hbo.com/data/content/global/videos/data/%s.xml" % videoid data = get_http_data(url) xml = ET.XML(data) ss = xml.find("videos") if is_py2_old: sa = list(ss.getiterator("size")) else: sa = list(ss.iter("size")) for i in sa: videourl = i.find("tv14").find("path").text match = re.search("/([a-z0-9]+:[a-z0-9]+)/", videourl) options.other = "-y %s" % videourl[videourl.index(match.group(1)):] yield RTMP(copy.copy(options), videourl[:videourl.index(match.group(1))], i.attrib["width"])
def merge(self): if self.detect is None: log.error( "Cant detect ffmpeg or avconv. Cant mux files without it.") return if self.stream.finished is False: return orig_filename = self.stream.options.output log.info("Merge audio and video into %s", orig_filename) tempfile = "{0}.temp".format(self.stream.options.output) audio_filename = "{0}.m4a".format( os.path.splitext(self.stream.options.output)[0]) arguments = [ "-c:v", "copy", "-c:a", "copy", "-f", "mp4", "-y", tempfile ] cmd = [self.detect, "-i", orig_filename, "-i", audio_filename] cmd += arguments p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: stderr = stderr.decode('utf-8', 'replace') msg = stderr.strip().split('\n')[-1] log.error("Something went wrong: %s", msg) return log.info("Merging done, removing old files.") os.remove(self.stream.options.output) os.remove(audio_filename) os.rename(tempfile, self.stream.options.output)
def get_media(url, options): if "http" not in url[:4]: url = "http://%s" % url if options.silent_semi: options.silent = True if options.verbose: log.debug("version: {0}".format(__version__)) stream = service_handler(sites, options, url) if not stream: generic = Generic(options, url) url, stream = generic.get(sites) if not stream: if re.search(".f4m", url) or re.search(".m3u8", url) or re.search( ".mpd", url): stream = Raw(options, url) if not stream: log.error( "That site is not supported. Make a ticket or send a message") sys.exit(2) if is_py2: url = ensure_unicode(url) if options.all_episodes: get_all_episodes(stream, copy.copy(options), url) else: get_one_media(stream, copy.copy(options))
def get(self): data = self.get_urldata() if self.exclude(): yield ServiceError("Excluding video") return match = re.search('="(http://www.expressen.se/tvspelare[^"]+)"', data) if not match: log.error("Can't find video id") return url = decode_html_entities(match.group(1)) data = self.http.request("get", url) match = re.search("window.Player.settings = ({.*});", data.text) if not match: log.error("Can't find json info.") dataj = json.loads(match.group(1)) if "streams" in dataj: if "iPad" in dataj["streams"]: streams = hlsparse( self.options, self.http.request("get", dataj["streams"]["iPad"]), dataj["streams"]["iPad"]) for n in list(streams.keys()): yield streams[n] if "hashHls" in dataj["streams"]: streams = hlsparse( self.options, self.http.request("get", dataj["streams"]["hashHls"]), dataj["streams"]["hashHls"]) for n in list(streams.keys()): yield streams[n]
def get(self, options): vid = None data = self.get_urldata() match = re.search(r'video url-([^"]+)', data) if not match: match = re.search(r'embed.jsp\?id=([^&]+)&', data) if not match: log.error("Cant find video id") sys.exit(2) vid = match.group(1) if not vid: path = unquote_plus(match.group(1)) data = get_http_data("http://www.svd.se%s" % path) match = re.search(r'embed.jsp\?id=([^&]+)&', data) if not match: log.error("Cant find video id2") sys.exit(2) vid = match.group(1) url = "http://amz.lwcdn.com/api/cache/VideoCache.jsp?id=%s" % vid data = get_http_data(url) xml = ET.XML(data) videofile = xml.find("{http://www.lemonwhale.com/xml11}VideoFile") mediafiles = videofile.find("{http://www.lemonwhale.com/xml11}MediaFiles") high = mediafiles.find("{http://www.lemonwhale.com/xml11}VideoURLHigh") if high.text: yield HTTP(copy.copy(options), high.text, 720) file = mediafiles.find("{http://www.lemonwhale.com/xml11}VideoURL").text yield HTTP(copy.copy(options), file, 480)
def get(self, options): match = re.search(r"urPlayer.init\((.*)\);", self.get_urldata()) if not match: log.error("Can't find json info") sys.exit(2) data = match.group(1) jsondata = json.loads(data) yield subtitle_tt(jsondata["subtitles"].split(",")[0]) basedomain = jsondata["streaming_config"]["streamer"]["redirect"] http = "http://%s/%s" % (basedomain, jsondata["file_html5"]) hd = None if len(jsondata["file_html5_hd"]) > 0: http_hd = "http://%s/%s" % (basedomain, jsondata["file_html5_hd"]) hls_hd = "%s%s" % (http_hd, jsondata["streaming_config"]["http_streaming"]["hls_file"]) tmp = jsondata["file_html5_hd"] match = re.search(".*(mp[34]:.*$)", tmp) path_hd = match.group(1) hd = True hls = "%s%s" % (http, jsondata["streaming_config"]["http_streaming"]["hls_file"]) rtmp = "rtmp://%s/%s" % (basedomain, jsondata["streaming_config"]["rtmp"]["application"]) path = "mp%s:%s" % (jsondata["file_flash"][-1], jsondata["file_flash"]) streams = hlsparse(hls) for n in list(streams.keys()): yield HLS(options, streams[n], n) options.other = "-v -a %s -y %s" % (jsondata["streaming_config"]["rtmp"]["application"], path) yield RTMP(options, rtmp, "480") if hd: streams = hlsparse(hls_hd) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n) options.other = "-v -a %s -y %s" % (jsondata["streaming_config"]["rtmp"]["application"], path_hd) yield RTMP(copy.copy(options), rtmp, "720")
def get(self, options): data = self.get_urldata() match = re.search('data-aptomaId="([-0-9a-z]+)"', data) if not match: log.error("Can't find video info") sys.exit(2) videoId = match.group(1) match = re.search(r'data-isLive="(\w+)"', data) if not match: log.error("Can't find live info") sys.exit(2) if match.group(1) == "true": options.live = True if not options.live: dataurl = "http://aftonbladet-play-metadata.cdn.drvideo.aptoma.no/video/%s.json" % videoId data = get_http_data(dataurl) data = json.loads(data) videoId = data["videoId"] streamsurl = "http://aftonbladet-play-static-ext.cdn.drvideo.aptoma.no/actions/video/?id=%s&formats&callback=" % videoId streams = json.loads(get_http_data(streamsurl)) hlsstreams = streams["formats"]["hls"] if "level3" in hlsstreams.keys(): hls = hlsstreams["level3"]["csmil"][0] else: hls = hlsstreams["akamai"]["m3u8"][0] address = hls["address"] path = hls["path"] for i in hls["files"]: if "filename" in i.keys(): playlist = "http://%s/%s/%s/master.m3u8" % (address, path, i["filename"]) else: playlist = "http://%s/%s/%s/master.m3u8" % (address, path, hls["filename"]) yield HLS(copy.copy(options), playlist, i["bitrate"])
def get(self, options): match = re.search("xmlUrl=([^ ]+)\" ", self.get_urldata()) if match: xmlurl = unquote_plus(match.group(1)) else: match = re.search("moviesList: \[\{\"VideoId\":\"(\d+)\"", self.get_urldata()) if not match: log.error("Can't find video id") sys.exit(2) vid = match.group(1) xmlurl = "http://www.expressen.se/Handlers/WebTvHandler.ashx?id=%s" % vid data = get_http_data(xmlurl) xml = ET.XML(data) live = xml.find("live").text if live != "0": options.live = True ss = xml.find("vurls") if is_py2_old: sa = list(ss.getiterator("vurl")) else: sa = list(ss.iter("vurl")) for i in sa: options2 = copy.copy(options) match = re.search(r"rtmp://([-0-9a-z\.]+/[-a-z0-9]+/)(.*)", i.text) filename = "rtmp://%s" % match.group(1) options2.other = "-y %s" % match.group(2) yield RTMP(options2, filename, int(i.attrib["bitrate"])) ipadurl = xml.find("mobileurls").find("ipadurl").text streams = hlsparse(ipadurl) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n)
def find_all_episodes(self, options): premium = False if options.username and options.password: premium = self._login(options.username, options.password) if isinstance(premium, Exception): log.error(premium.message) return None jsondata = self._get_show_info() episodes = [] n = 1 for i in jsondata["results"]: if premium: text = "availability_group_premium" else: text = "availability_group_free" days = self._getdays(i, text) if premium and days == 0: days = self._getdays(i, "availability_group_free") if days > 0: video_id = i["id"] url = "http://www.tv4play.se/program/%s?video_id=%s" % ( i["program"]["nid"], video_id) episodes.append(url) if n == options.all_last: break n += 1 return episodes
def get_media(url, options): if "http" not in url[:4]: url = "http://%s" % url if options.silent_semi: options.silent = True stream = service_handler(sites, options, url) if not stream: generic = Generic(options, url) url, stream = generic.get(sites) if not stream: if url.find(".f4m") > 0 or url.find(".m3u8") > 0: stream = Raw(options, url) if not stream: log.error( "That site is not supported. Make a ticket or send a message") sys.exit(2) if is_py2: url = ensure_unicode(url) if options.all_episodes: get_all_episodes(stream, options, url) else: get_one_media(stream, options)
def output(options, extension="mp4", openfd=True, mode="wb", **kwargs): subtitlefiles = ["srt", "smi", "tt", "sami", "wrst"] ext = re.search(r"(\.\w{2,4})$", options.output) if not ext: options.output = "%s.%s" % (options.output, extension) if options.output_auto and ext: options.output = "%s.%s" % (options.output, extension) elif extension == "srt" and ext: options.output = "%s.srt" % options.output[:options.output.rfind(ext.group(1))] if ext and extension == "srt" and ext.group(1).split(".")[-1] in subtitlefiles: options.output = "%s.srt" % options.output[:options.output.rfind(ext.group(1))] log.info("Outfile: %s", options.output) if os.path.isfile(options.output) or \ findexpisode(os.path.dirname(os.path.realpath(options.output)), options.service, os.path.basename(options.output)): if extension in subtitlefiles: if not options.force_subtitle: log.error("File (%s) already exists. Use --force-subtitle to overwrite" % options.output) return None else: if not options.force: log.error("File (%s) already exists. Use --force to overwrite" % options.output) return None if openfd: file_d = open(options.output, mode, **kwargs) return file_d return True
def remux(self): if self.detect is None: log.error("Cant detect ffmpeg or avconv. Cant mux files without it.") return if self.stream.finished is False: return if self.stream.options.output.endswith('.mp4') is False: orig_filename = self.stream.options.output new_name = "{0}.mp4".format(os.path.splitext(self.stream.options.output)[0]) log.info("Muxing %s into %s", orig_filename, new_name) tempfile = "{0}.temp".format(self.stream.options.output) name, ext = os.path.splitext(orig_filename) arguments = ["-c", "copy", "-copyts", "-f", "mp4"] if ext == ".ts": arguments += ["-bsf:a", "aac_adtstoasc"] arguments += ["-y", tempfile] cmd = [self.detect, "-i", orig_filename] cmd += arguments p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: stderr = stderr.decode('utf-8', 'replace') msg = stderr.strip().split('\n')[-1] log.error("Something went wrong: %s", msg) return log.info("Muxing done, removing the old file.") os.remove(self.stream.options.output) os.rename(tempfile, new_name)
def find_all_episodes(self, options): match = re.search(r'<link rel="alternate" type="application/rss\+xml" [^>]*href="([^"]+)"', self.get_urldata()[1]) if match is None: match = re.findall(r'a class="play[^"]+"\s+href="(/video[^"]+)"', self.get_urldata()[1]) if not match: log.error("Couldn't retrieve episode list") return episodes = [urljoin("http://www.svtplay.se", x) for x in match] else: error, data = get_http_data(match.group(1)) if error: log.error("Cant get rss page") return xml = ET.XML(data) episodes = [x.text for x in xml.findall(".//item/link")] episodes_new = [] n = 1 for i in episodes: episodes_new.append(i) if n == options.all_last: break n += 1 return sorted(episodes_new)
def get(self, options): error, data = self.get_urldata() if error: log.error("Can't download webpage") return if self.exclude(options): return parse = urlparse(self.url) vidoid = parse.path[parse.path.rfind("/")+1:] match = re.search(r'JSONdata = ({.*});', data) if not match: log.error("Cant find json data") return janson = json.loads(match.group(1)) playlist = janson["playlist"] for i in playlist: if i["brightcoveId"] == vidoid: if i["HLSURL"]: streams = hlsparse(i["HLSURL"]) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n) for n in i["renditions"]: if n["container"] == "MP4": yield HTTP(copy.copy(options), n["URL"], int(n["rate"])/1000)
def download(self): """ Get the stream from RTMP """ args = [] if self.options.live: args.append("-v") if self.options.resume: args.append("-e") file_d = output(self.options, self.options.output, "flv", False) if file_d is None: return args += ["-o", self.options.output] if self.options.silent or self.options.output == "-": args.append("-q") if self.options.other: if is_py2: args += shlex.split(self.options.other.encode("utf-8")) else: args += shlex.split(self.options.other) if self.options.verbose: args.append("-V") command = ["rtmpdump", "-r", self.url] + args log.debug("Running: %s", " ".join(command)) try: subprocess.call(command) except OSError as e: log.error("Could not execute rtmpdump: " + e.strerror)
def find_all_episodes(self, options): match = re.search(r"data-franchise='([^']+)'", self.get_urldata()) if match is None: log.error("Couldn't program id") sys.exit(2) programid = match.group(1) match = re.findall( r"<li class='(divider playlist-item|playlist-item)'( data-item-id='([^']+)')?", self.get_urldata()) if not match: log.error("Couldn't retrieve episode list") sys.exit(2) episodNr = [] for i in match: if i[0] == "playlist-item": episodNr.append(i[2]) else: break episodes = [] for i in sorted(episodNr): episodes.append( "http://www.nickelodeon.se/serier/%s-something/videos/%s-something" % (programid, i)) return episodes
def get(self, options): match = re.search(r'mrss\s+:\s+"([^"]+)"', self.get_urldata()) if not match: log.error("Can't find id for the video") sys.exit(2) swfurl = re.search(r'embedSWF\( "([^"]+)"', self.get_urldata()) options.other = "-W %s" % swfurl.group(1) data = get_http_data(match.group(1)) xml = ET.XML(data) mediagen = xml.find("channel").find("item").find( "{http://search.yahoo.com/mrss/}group") title = xml.find("channel").find("item").find("title").text if options.output_auto: directory = os.path.dirname(options.output) if len(directory): options.output = "%s/%s" % (directory, title) else: options.output = title contenturl = mediagen.find( "{http://search.yahoo.com/mrss/}content").attrib["url"] content = get_http_data(contenturl) xml = ET.XML(content) ss = xml.find("video").find("item") if is_py2_old: sa = list(ss.getiterator("rendition")) else: sa = list(ss.iter("rendition")) for i in sa: yield RTMP(options, i.find("src").text, i.attrib["bitrate"])
def get(self, options): vid = None data = self.get_urldata() match = re.search(r'video url-([^"]+)', data) if not match: match = re.search(r'embed.jsp\?id=([^&]+)&', data) if not match: log.error("Cant find video id") sys.exit(2) vid = match.group(1) if not vid: path = unquote_plus(match.group(1)) data = get_http_data("http://www.svd.se%s" % path) match = re.search(r'embed.jsp\?id=([^&]+)&', data) if not match: log.error("Cant find video id2") sys.exit(2) vid = match.group(1) url = "http://amz.lwcdn.com/api/cache/VideoCache.jsp?id=%s" % vid data = get_http_data(url) xml = ET.XML(data) videofile = xml.find("{http://www.lemonwhale.com/xml11}VideoFile") mediafiles = videofile.find( "{http://www.lemonwhale.com/xml11}MediaFiles") high = mediafiles.find("{http://www.lemonwhale.com/xml11}VideoURLHigh") if high.text: yield HTTP(copy.copy(options), high.text, 720) videourl = mediafiles.find( "{http://www.lemonwhale.com/xml11}VideoURL").text yield HTTP(copy.copy(options), videourl, 480)
def find_all_episodes(self, options): page = 1 match = re.search(r'"http://www.oppetarkiv.se/etikett/titel/([^"/]+)', self.get_urldata()) if match is None: match = re.search( r'"http://www.oppetarkiv.se/etikett/titel/([^"/]+)', self.url) if match is None: log.error("Couldn't find title") sys.exit(2) program = match.group(1) more = True episodes = [] while more: url = "http://www.oppetarkiv.se/etikett/titel/%s/?sida=%s&sort=tid_stigande&embed=true" % ( program, page) data = get_http_data(url) visa = re.search(r'svtXColorDarkLightGrey', data) if not visa: more = False regex = re.compile(r'(http://www.oppetarkiv.se/video/[^"]+)') for match in regex.finditer(data): episodes.append(match.group(1)) page += 1 return episodes
def find_all_episodes(self, options): page = 1 data = self.get_urldata() match = re.search(r'"/etikett/titel/([^"/]+)', data) if match is None: match = re.search(r'"http://www.oppetarkiv.se/etikett/titel/([^/]+)/', self.url) if match is None: log.error("Couldn't find title") return program = match.group(1) more = True episodes = [] n = 0 if options.all_last > 0: sort = "tid_fallande" else: sort = "tid_stigande" while more: url = "http://www.oppetarkiv.se/etikett/titel/%s/?sida=%s&sort=%s&embed=true" % (program, page, sort) data = self.http.request("get", url).text visa = re.search(r'svtXColorDarkLightGrey', data) if not visa: more = False regex = re.compile(r'href="(/video/[^"]+)"') for match in regex.finditer(data): if n == options.all_last: break episodes.append("http://www.oppetarkiv.se%s" % match.group(1)) n += 1 page += 1 return episodes
def find_all_episodes(self, options): format_id = re.search(r'data-format-id="(\d+)"', self.get_urldata()) if not format_id: log.error("Can't find video info for all episodes") return data = self.http.request("get", "http://playapi.mtgx.tv/v1/sections?sections=videos.one,seasons.videolist&format=%s" % format_id.group(1)).text videos = [] jsondata = json.loads(data) jsons = jsondata["_embedded"]["sections"][1]["_embedded"]["seasons"] for i in jsons: grej = i["_embedded"]["episodelist"] if "_links" in grej and "_embedded" not in grej: data2 = self.http.request("get", grej["_links"]["self"]["href"]).json() for x in data2["_embedded"]["videos"]: videos.append(x) if "_embedded" in grej: for x in grej["_embedded"]["videos"]: videos.append(x) n = 0 episodes = [] for i in videos: if n == options.all_last: break episodes.append(i["sharing"]["url"]) n += 1 return episodes
def merge(self): if self.detect is None: log.error("Cant detect ffmpeg or avconv. Cant mux files without it.") return if self.stream.finished is False: return orig_filename = self.stream.options.output log.info("Merge audio and video into %s", orig_filename) tempfile = "{0}.temp".format(self.stream.options.output) audio_filename = "{0}.m4a".format(os.path.splitext(self.stream.options.output)[0]) arguments = ["-c:v", "copy", "-c:a", "copy", "-f", "mp4", "-y", tempfile] cmd = [self.detect, "-i", orig_filename, "-i", audio_filename] cmd += arguments p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: stderr = stderr.decode('utf-8', 'replace') msg = stderr.strip().split('\n')[-1] log.error("Something went wrong: %s", msg) return log.info("Merging done, removing old files.") os.remove(self.stream.options.output) os.remove(audio_filename) os.rename(tempfile, self.stream.options.output)
def get(self, options, url): data = get_http_data(url) match = re.search("xmlUrl: '(http://www.expressen.*)'", data) if not match: log.error("Can't find video file") sys.exit(2) url = "http://tv.expressen.se/%s/?standAlone=true&output=xml" % quote_plus(match.group(1)) url = match.group(1) data = get_http_data(url) xml = ET.XML(data) ss = xml.find("vurls") if sys.version_info < (2, 7): sa = list(ss.getiterator("vurl")) else: sa = list(ss.iter("vurl")) streams = {} for i in sa: streams[int(i.attrib["bitrate"])] = i.text test = select_quality(options, streams) filename = test match = re.search("rtmp://([0-9a-z\.]+/[0-9]+/)(.*)", filename) filename = "rtmp://%s" % match.group(1) options.other = "-y %s" % match.group(2) download_rtmp(options, filename)
def findvid(url, data): parse = urlparse(url) if "tv4play.se" in url: try: vid = parse_qs(parse.query)["video_id"][0] except KeyError: return None else: match = re.search(r"\"vid\":\"(\d+)\",", data) if match: vid = match.group(1) else: match = re.search(r"-(\d+)$", url) if match: vid = match.group(1) else: match = re.search( r"meta content='([^']+)' property='og:video'", data) if match: match = re.search(r"vid=(\d+)&", match.group(1)) if match: vid = match.group(1) else: log.error("Can't find video id for %s", url) return else: return None return vid
def get(self, options): match = re.search("xmlUrl=([^ ]+)\" ", self.get_urldata()) if match: xmlurl = unquote_plus(match.group(1)) else: match = re.search(r"moviesList: \[\{\"VideoId\":\"(\d+)\"", self.get_urldata()) if not match: log.error("Can't find video id") sys.exit(2) vid = match.group(1) xmlurl = "http://www.expressen.se/Handlers/WebTvHandler.ashx?id=%s" % vid data = get_http_data(xmlurl) xml = ET.XML(data) live = xml.find("live").text if live != "0": options.live = True ss = xml.find("vurls") if is_py2_old: sa = list(ss.getiterator("vurl")) else: sa = list(ss.iter("vurl")) for i in sa: options2 = copy.copy(options) match = re.search(r"rtmp://([-0-9a-z\.]+/[-a-z0-9]+/)(.*)", i.text) filename = "rtmp://%s" % match.group(1) options2.other = "-y %s" % match.group(2) yield RTMP(options2, filename, int(i.attrib["bitrate"])) ipadurl = xml.find("mobileurls").find("ipadurl").text streams = hlsparse(ipadurl) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n)
def query(self): random_sentences = ' '.join(sample(parse(self), 8)).replace('\r\n', '') url = 'https://whatlanguage.herokuapp.com' payload = {"query": random_sentences} headers = { 'content-type': 'application/json' } # Note: requests handles json from version 2.4.2 and onwards so i use json.dumps for now. try: r = post( url, data=dumps(payload), headers=headers, timeout=30 ) # Note: reasonable timeout i guess? svtplay-dl is mainly used while multitasking i presume, and it is heroku after all (fast enough) if r.status_code == codes.ok: response = r.json() return response['language'] else: log.error( "Server error appeared. Setting language as undetermined." ) return 'und' except Timeout: log.error( "30 seconds server timeout reached. Setting language as undetermined." ) return 'und'
def get(self): parse = urlparse(self.url) try: other = parse.fragment except KeyError: log.error("Something wrong with that url") return match = re.search("^/(.*).html", other) if not match: log.error("Cant find video file") return url = "http://www.hbo.com/data/content/{0}.xml".format(match.group(1)) data = self.http.request("get", url).content xml = ET.XML(data) videoid = xml.find("content")[1].find("videoId").text url = "http://render.cdn.hbo.com/data/content/global/videos/data/{0}.xml".format( videoid) data = self.http.request("get", url).content xml = ET.XML(data) ss = xml.find("videos") sa = list(ss.iter("size")) for i in sa: videourl = i.find("tv14").find("path").text match = re.search("/([a-z0-9]+:[a-z0-9]+)/", videourl) self.options.other = "-y {0}".format( videourl[videourl.index(match.group(1)):]) yield RTMP(copy.copy(self.options), videourl[:videourl.index(match.group(1))], i.attrib["width"])
def output(options, extension="mp4", openfd=True, mode="wb", **kwargs): subtitlefiles = ["srt", "smi", "tt","sami", "wrst"] ext = re.search(r"(\.\w{2,4})$", options.output) if not ext: options.output = "%s.%s" % (options.output, extension) if options.output_auto and ext: options.output = "%s.%s" % (options.output, extension) elif extension == "srt" and ext: options.output = "%s.srt" % options.output[:options.output.rfind(ext.group(1))] if ext and extension == "srt" and ext.group(1).split(".")[-1] in subtitlefiles: options.output = "%s.srt" % options.output[:options.output.rfind(ext.group(1))] log.info("Outfile: %s", options.output) if os.path.isfile(options.output) or \ findexpisode(os.path.dirname(os.path.realpath(options.output)), options.service, os.path.basename(options.output)): if extension in subtitlefiles: if not options.force_subtitle: log.error("File (%s) already exists. Use --force-subtitle to overwrite" % options.output) return None else: if not options.force: log.error("File (%s) already exists. Use --force to overwrite" % options.output) return None if openfd: file_d = open(options.output, mode, **kwargs) return file_d return True
def get_media(url, options): stream = service_handler(url) if not stream: url, stream = Generic().get(url) if not stream: log.error("That site is not supported. Make a ticket or send a message") sys.exit(2) if options.all_episodes: if options.output and not os.path.isdir(options.output): log.error("Output must be a directory if used with --all-episodes") sys.exit(2) episodes = stream.find_all_episodes(options) for idx, o in enumerate(episodes): if o == url: substream = stream else: substream = service_handler(o) log.info("Episode %d of %d", idx + 1, len(episodes)) # get_one_media overwrites options.output... get_one_media(substream, copy.copy(options)) else: get_one_media(stream, options)
def download(self): """ Get the stream from RTMP """ self.output_extention = "flv" args = [] if self.config.get("live"): args.append("-v") if self.config.get("resume"): args.append("-e") file_d = output(self.output, self.config, "flv", False) if file_d is None: return args += ["-o", formatname(self.output, self.config, "flv")] if self.config.get("silent"): args.append("-q") if self.kwargs.get("other"): args += shlex.split(self.kwargs.pop("other")) if self.config.get("verbose"): args.append("-V") command = ["rtmpdump", "-r", self.url] + args log.debug("Running: {0}".format(" ".join(command))) try: subprocess.call(command) except OSError as e: log.error("Could not execute rtmpdump: {0}".format(e.strerror)) return self.finished = True
def get(self, options, url): parse = urlparse(url) try: other = parse[5] except KeyError: log.error("Something wrong with that url") sys.exit(2) match = re.search("^/(.*).html", other) if not match: log.error("Cant find video file") sys.exit(2) url = "http://www.hbo.com/data/content/%s.xml" % match.group(1) data = get_http_data(url) xml = ET.XML(data) videoid = xml.find("content")[1].find("videoId").text url = "http://render.cdn.hbo.com/data/content/global/videos/data/%s.xml" % videoid data = get_http_data(url) xml = ET.XML(data) ss = xml.find("videos") if sys.version_info < (2, 7): sa = list(ss.getiterator("size")) else: sa = list(ss.iter("size")) streams = {} for i in sa: stream = {} stream["path"] = i.find("tv14").find("path").text streams[int(i.attrib["width"])] = stream test = select_quality(options, streams) download_rtmp(options, test["path"])
def find_all_episodes(self, options): premium = False if options.username and options.password: premium = self._login(options.username, options.password) if isinstance(premium, Exception): log.error(premium.message) return None jsondata = self._get_show_info() episodes = [] n = 1 for i in jsondata["results"]: if premium: text = "availability_group_premium" else: text = "availability_group_free" try: days = int(i["availability"][text]) except (ValueError, TypeError): days = 999 if days > 0: video_id = i["id"] url = "http://www.tv4play.se/program/%s?video_id=%s" % ( show, video_id) episodes.append(url) if n == options.all_last: break n += 1 return episodes
def find_all_episodes(self, config): match = re.search(r"data-franchise='([^']+)'", self.get_urldata()) if match is None: log.error("Couldn't program id") return programid = match.group(1) match = re.findall( r"<li class='([a-z]+ )?playlist-item( [a-z]+)*?'( data-[-a-z]+='[^']+')* data-item-id='([^']+)'", self.get_urldata()) if not match: log.error("Couldn't retrieve episode list") return episodNr = [] for i in match: episodNr.append(i[3]) episodes = [] n = 0 for i in sorted(episodNr): if n == config.get("all_last"): break episodes.append( "http://www.nickelodeon.se/serier/{0}-something/videos/{1}-something" .format(programid, i)) n += 1 return episodes
def download(self): """ Get the stream from RTMP """ args = [] if self.options.live: args.append("-v") if self.options.resume: args.append("-e") file_d = output(self.options, "flv", False) if file_d is None: return args += ["-o", self.options.output] if self.options.silent or self.options.output == "-": args.append("-q") if self.options.other: if is_py2: args += shlex.split(self.options.other.encode("utf-8")) else: args += shlex.split(self.options.other) if self.options.verbose: args.append("-V") command = ["rtmpdump", "-r", self.url] + args log.debug("Running: %s", " ".join(command)) try: subprocess.call(command) except OSError as e: log.error("Could not execute rtmpdump: " + e.strerror) return self.finished = True
def get(self, options): match = re.search(r'data-videoid="([^"]+)"', self.get_urldata()) if not match: parse = urlparse(self.url) match = re.search(r'video/(\d+)/', parse.fragment) if not match: log.error("Can't find video id") sys.exit(2) videoid = match.group(1) data = get_http_data("http://svp.vg.no/svp/api/v1/vgtv/assets/%s?appName=vgtv-website" % videoid) jsondata = json.loads(data) if options.output_auto: directory = os.path.dirname(options.output) title = "%s" % jsondata["title"] title = filenamify(title) if len(directory): options.output = "%s/%s" % (directory, title) else: options.output = title if "hds" in jsondata["streamUrls"]: parse = urlparse(jsondata["streamUrls"]["hds"]) manifest = "%s://%s%s?%s&hdcore=3.3.0" % (parse.scheme, parse.netloc, parse.path, parse.query) streams = hdsparse(copy.copy(options), manifest) if streams: for n in list(streams.keys()): yield streams[n] if "hls" in jsondata["streamUrls"]: streams = hlsparse(jsondata["streamUrls"]["hls"]) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n) if "mp4" in jsondata["streamUrls"]: yield HTTP(copy.copy(options), jsondata["streamUrls"]["mp4"])
def output(options, extention="mp4", openfd=True, mode="wb", **kwargs): if is_py2: file_d = file else: file_d = io.IOBase if options.output != "-": ext = re.search(r"(\.\w{2,3})$", options.output) if not ext: options.output = "%s.%s" % (options.output, extention) if options.output_auto and ext: options.output = "%s.%s" % (options.output, extention) if extention == "srt" and ext: options.output = "%s.srt" % options.output[:options.output.rfind(ext.group(1))] log.info("Outfile: %s", options.output) if os.path.isfile(options.output) or \ findexpisode(os.path.dirname(os.path.realpath(options.output)), options.service, os.path.basename(options.output)): if extention == "srt": if not options.force_subtitle: log.error("File (%s) already exists. Use --force-subtitle to overwrite" % options.output) return None else: if not options.force: log.error("File (%s) already exists. Use --force to overwrite" % options.output) return None if openfd: file_d = open(options.output, mode, **kwargs) else: if openfd: if is_py2: file_d = sys.stdout else: file_d = sys.stdout.buffer return file_d
def get(self): data = self.get_urldata() if self.exclude(): yield ServiceError("Excluding video") return match = re.search('="(https://www.expressen.se/tvspelare[^"]+)"', data) if not match: log.error("Can't find video id") return url = decode_html_entities(match.group(1)) data = self.http.request("get", url) match = re.search("window.Player.settings = ({.*});", data.text) if not match: log.error("Can't find json info.") dataj = json.loads(match.group(1)) if "streams" in dataj: if "iPad" in dataj["streams"]: streams = hlsparse(self.options, self.http.request("get", dataj["streams"]["iPad"]), dataj["streams"]["iPad"]) for n in list(streams.keys()): yield streams[n] if "hashHls" in dataj["streams"]: streams = hlsparse(self.options, self.http.request("get", dataj["streams"]["hashHls"]), dataj["streams"]["hashHls"]) for n in list(streams.keys()): yield streams[n]
def get(self, options): error, data = self.get_urldata() if error: log.error("Can't get the page") return if self.exclude(options): return extention = False filename = os.path.basename(self.url[:self.url.rfind("/")-1]) if options.output and os.path.isdir(options.output): options.output = "%s/%s" % (os.path.dirname(options.output), filename) extention = True elif options.output is None: options.output = "%s" % filename extention = True if self.url.find(".f4m") > 0: if extention: options.output = "%s.flv" % options.output streams = hdsparse(copy.copy(options), self.url) if streams: for n in list(streams.keys()): yield streams[n] if self.url.find(".m3u8") > 0: streams = hlsparse(self.url) if extention: options.output = "%s.ts" % options.output for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n)
def get_all_episodes(stream, options, url): if options.output and os.path.isfile(options.output): log.error("Output must be a directory if used with --all-episodes") sys.exit(2) elif options.output and not os.path.exists(options.output): try: os.makedirs(options.output) except OSError as e: log.error("%s: %s", e.strerror, e.filename) return episodes = stream.find_all_episodes(options) if episodes is None: return for idx, o in enumerate(episodes): if o == url: substream = stream else: substream = service_handler(sites, copy.copy(options), o) log.info("Episode %d of %d", idx + 1, len(episodes)) log.info("Url: %s",o) # get_one_media overwrites options.output... get_one_media(substream, copy.copy(options))
def output(options, filename, extention="mp4", openfd=True): if is_py3: file_d = io.IOBase else: file_d = file if options.output != "-": ext = re.search(r"(\.[a-z0-9]+)$", filename) if not ext: options.output = "%s.%s" % (options.output, extention) log.info("Outfile: %s", options.output) if (os.path.isfile(options.output) or \ findexpisode(os.path.dirname(os.path.realpath(options.output)), options.service, os.path.basename(options.output))) and \ not options.force: log.error("File already exists. Use --force to overwrite") return None if openfd: file_d = open(options.output, "wb") else: if openfd: if is_py3: file_d = sys.stdout.buffer else: file_d = sys.stdout return file_d
def find_all_episodes(self, options): page = 1 data = self.get_urldata() match = re.search(r'"/etikett/titel/([^"/]+)', data) if match is None: match = re.search(r'"http://www.oppetarkiv.se/etikett/titel/([^/]+)/', self.url) if match is None: log.error("Couldn't find title") return program = match.group(1) episodes = [] n = 0 if self.options.all_last > 0: sort = "tid_fallande" else: sort = "tid_stigande" while True: url = "http://www.oppetarkiv.se/etikett/titel/%s/?sida=%s&sort=%s&embed=true" % (program, page, sort) data = self.http.request("get", url) if data.status_code == 404: break data = data.text regex = re.compile(r'href="(/video/[^"]+)"') for match in regex.finditer(data): if n == self.options.all_last: break episodes.append("http://www.oppetarkiv.se%s" % match.group(1)) n += 1 page += 1 return episodes
def find_all_episodes(self, options): program = re.search(".*/program/(\d+)", self.url) if not program: log.error("Can't find program id in url") return None baseurl = "http://www.kanal5play.se/content/program/%s" % program.group(1) data = self.http.request("get", baseurl).text sasong = re.search("/program/\d+/sasong/(\d+)", data) if not sasong: log.error("Can't find seasong id") return None seasong = int(sasong.group(1)) episodes = [] n = 0 more = True while more: url = "%s/sasong/%s" % (baseurl, seasong) data = self.http.request("get", url) if data.status_code == 404: more = False else: regex = re.compile(r'href="(/play/program/\d+/video/\d+)"') for match in regex.finditer(data.text): if n == options.all_last: break url2 = "http://www.kanal5play.se%s" % match.group(1) if url2 not in episodes: episodes.append(url2) n += 1 seasong -= 1 return episodes
def find_all_episodes(self, options): page = 1 data = self.get_urldata() match = re.search(r'"/etikett/titel/([^"/]+)', data) if match is None: match = re.search(r'"http://www.oppetarkiv.se/etikett/titel/([^/]+)/', self.url) if match is None: log.error("Couldn't find title") return program = match.group(1) episodes = [] n = 0 if self.options.all_last > 0: sort = "tid_fallande" else: sort = "tid_stigande" while True: url = "http://www.oppetarkiv.se/etikett/titel/{0}/?sida={1}&sort={2}&embed=true".format(program, page, sort) data = self.http.request("get", url) if data.status_code == 404: break data = data.text regex = re.compile(r'href="(/video/[^"]+)"') for match in regex.finditer(data): if n == self.options.all_last: break episodes.append("http://www.oppetarkiv.se{0}".format(match.group(1))) n += 1 page += 1 return episodes
def findvid(url, data): parse = urlparse(url) if "tv4play.se" in url: try: vid = parse_qs(parse.query)["video_id"][0] except KeyError: return None else: match = re.search(r"\"vid\":\"(\d+)\",", data) if match: vid = match.group(1) else: match = re.search(r"-(\d+)$", url) if match: vid = match.group(1) else: match = re.search(r"meta content='([^']+)' property='og:video'", data) if match: match = re.search(r"vid=(\d+)&", match.group(1)) if match: vid = match.group(1) else: log.error("Can't find video id for %s", url) return else: return None return vid
def remux(self): if self.detect is None: log.error( "Cant detect ffmpeg or avconv. Cant mux files without it.") return if self.stream.finished is False: return if self.stream.options.output.endswith('.mp4') is False: orig_filename = self.stream.options.output new_name = "{0}.mp4".format( os.path.splitext(self.stream.options.output)[0]) log.info("Muxing %s into %s", orig_filename, new_name) tempfile = "{0}.temp".format(self.stream.options.output) name, ext = os.path.splitext(orig_filename) arguments = ["-c", "copy", "-copyts", "-f", "mp4"] if ext == ".ts": arguments += ["-bsf:a", "aac_adtstoasc"] arguments += ["-y", tempfile] cmd = [self.detect, "-i", orig_filename] cmd += arguments p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0: stderr = stderr.decode('utf-8', 'replace') msg = stderr.strip().split('\n')[-1] log.error("Something went wrong: %s", msg) return log.info("Muxing done, removing the old file.") os.remove(self.stream.options.output) os.rename(tempfile, new_name)
def main(): """ Main program """ usage = "usage: %prog [options] url" parser = OptionParser(usage=usage, version=__version__) parser.add_option("-o", "--output", metavar="OUTPUT", help="Outputs to the given filename.") parser.add_option("-r", "--resume", action="store_true", dest="resume", default=False, help="Resume a download (RTMP based ones)") parser.add_option("-l", "--live", action="store_true", dest="live", default=False, help="Enable for live streams (RTMP based ones)") parser.add_option("-s", "--silent", action="store_true", dest="silent", default=False) parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False) parser.add_option("-f", "--force", action="store_true", dest="force", default=False) parser.add_option("-q", "--quality", default=0, metavar="quality", help="Choose what format to download.\nIt will download the best format by default") parser.add_option("-Q", "--flexible-quality", default=0, metavar="amount", dest="flexibleq", help="Allow given quality (as above) to differ by an amount.") parser.add_option("-H", "--hls", action="store_true", dest="hls", default=False, help="obsolete use -P") parser.add_option("-S", "--subtitle", action="store_true", dest="subtitle", default=False, help="Download subtitle from the site if available.") parser.add_option("--force-subtitle", dest="force_subtitle", default=False, action="store_true", help="Download only subtitle if its used with -S") parser.add_option("-u", "--username", default=None, help="Username") parser.add_option("-p", "--password", default=None, help="Password") parser.add_option("-t", "--thumbnail", action="store_true", dest="thumbnail", default=False, help="Download thumbnail from the site if available.") parser.add_option("-A", "--all-episodes", action="store_true", dest="all_episodes", default=False, help="Try to download all episodes.") parser.add_option("-P", "--preferred", default=None, metavar="preferred", help="preferred download method (rtmp, hls or hds)") (options, args) = parser.parse_args() if not args: parser.print_help() sys.exit(0) if len(args) != 1: parser.error("incorrect number of arguments") options = mergeParserOption(Options(), options) setup_log(options.silent, options.verbose) if options.flexibleq and not options.quality: log.error("flexible-quality requires a quality") sys.exit(4) url = args[0] try: get_media(url, options) except KeyboardInterrupt: print("")
def get_all_episodes(stream, url): name = os.path.dirname(formatname(dict(), stream.config)) if name and os.path.isfile(name): log.error("Output must be a directory if used with --all-episodes") sys.exit(2) elif name and not os.path.exists(name): try: os.makedirs(name) except OSError as e: log.error("%s: %s", e.strerror, e.filename) return episodes = stream.find_all_episodes(stream.config) if episodes is None: return for idx, o in enumerate(episodes): if o == url: substream = stream else: substream = service_handler(sites, copy.copy(stream.config), o) log.info("Episode %d of %d", idx + 1, len(episodes)) log.info("Url: %s", o) # get_one_media overwrites options.output... get_one_media(substream)
def get_media(url, options): if "http" not in url[:4]: url = "http://%s" % url if options.silent_semi: options.silent = True if options.verbose: log.debug("version: {0}".format( __version__)) stream = service_handler(sites, options, url) if not stream: generic = Generic(options, url) url, stream = generic.get(sites) if not stream: if url.find(".f4m") > 0 or url.find(".m3u8") > 0: stream = Raw(options, url) if not stream: log.error("That site is not supported. Make a ticket or send a message") sys.exit(2) if is_py2: url = ensure_unicode(url) if options.all_episodes: get_all_episodes(stream, copy.copy(options), url) else: get_one_media(stream, copy.copy(options))
def merge(self): if self.detect is None: log.error("Cant detect ffmpeg or avconv. Cant mux files without it.") return if self.stream.finished is False: return orig_filename = formatname(self.stream.output, self.config, self.stream.output_extention) cmd = [self.detect, "-i", orig_filename] _, stdout, stderr = run_program(cmd, False) # return 1 is good here. videotrack, audiotrack = self._checktracks(stderr) if self.config.get("merge_subtitle"): log.info("Merge audio, video and subtitle into {0}".format(orig_filename)) else: log.info("Merge audio and video into {0}".format(orig_filename)) tempfile = u"{0}.temp".format(orig_filename) name, ext = os.path.splitext(orig_filename) arguments = ["-c:v", "copy", "-c:a", "copy", "-f", "mp4"] if ext == ".ts": audio_filename = u"{0}.audio.ts".format(name) arguments += ["-bsf:a", "aac_adtstoasc"] else: audio_filename = u"{0}.m4a".format(name) cmd = [self.detect, "-i", orig_filename, "-i", audio_filename] if self.config.get("merge_subtitle"): langs = self.sublanguage() for stream_num, language in enumerate(langs, start=audiotrack + 1): arguments += ["-map", "{}".format(videotrack), "-map", "{}".format(audiotrack), "-map", str(stream_num), "-c:s:" + str(stream_num - 2), "mov_text", "-metadata:s:s:" + str(stream_num - 2), "language=" + language] if self.subfixes and len(self.subfixes) >= 2: for subfix in self.subfixes: subfile = "{0}.srt".format(name + subfix) cmd += ["-i", subfile] else: subfile = "{0}.srt".format(name) cmd += ["-i", subfile] arguments += ["-y", tempfile] cmd += arguments returncode, stdout, stderr = run_program(cmd) if returncode != 0: return log.info("Merging done, removing old files.") os.remove(orig_filename) os.remove(audio_filename) if self.config.get("merge_subtitle") and not self.config.get("subtitle"): if self.subfixes and len(self.subfixes) >= 2: for subfix in self.subfixes: subfile = "{0}.srt".format(name + subfix) os.remove(subfile) else: os.remove(subfile) os.rename(tempfile, orig_filename)
def find_all_episodes(self, options): parse = urlparse(self._url) if len(parse.path) > 7 and parse.path[-7:] == "rss.xml": match = self.url else: match = re.search( r'<link rel="alternate" type="application/rss\+xml" [^>]*href="([^"]+)"', self.get_urldata()) if match: match = match.group(1) if match is None: videos = [] tab = None match = re.search("__svtplay'] = ({.*});", self.get_urldata()) if re.search("sista-chansen", parse.path): videos = self._last_chance(videos, 1) elif not match: log.error("Couldn't retrieve episode list") return else: dataj = json.loads(match.group(1)) if re.search("/genre", parse.path): videos = self._genre(dataj) else: if parse.query: match = re.search("tab=(.+)", parse.query) if match: tab = match.group(1) items = dataj["videoTitlePage"]["relatedVideosTabs"] for i in items: if tab: if i["slug"] == tab: videos = self.videos_to_list( i["videos"], videos) else: if "sasong" in i["slug"] or "senast" in i["slug"]: videos = self.videos_to_list( i["videos"], videos) if self.options.include_clips: if i["slug"] == "klipp": videos = self.videos_to_list( i["videos"], videos) episodes = [urljoin("http://www.svtplay.se", x) for x in videos] else: data = self.http.request("get", match).content xml = ET.XML(data) episodes = [x.text for x in xml.findall(".//item/link")] if options.all_last > 0: return sorted(episodes[-options.all_last:]) return sorted(episodes)
def get(self, options): parse = urlparse(self.url) if parse.hostname == "video.disney.se": match = re.search(r"Grill.burger=({.*}):", self.get_urldata()) if not match: log.error("Can't find video info") return jsondata = json.loads(match.group(1)) for n in jsondata["stack"]: if len(n["data"]) > 0: for x in n["data"]: if "flavors" in x: for i in x["flavors"]: if i["format"] == "mp4": yield HTTP(copy.copy(options), i["url"], i["bitrate"]) else: match = re.search(r"uniqueId : '([^']+)'", self.get_urldata()) if not match: log.error("Can't find video info") return uniq = match.group(1) match = re.search("entryId : '([^']+)'", self.get_urldata()) entryid = match.group(1) match = re.search("partnerId : '([^']+)'", self.get_urldata()) partnerid = match.group(1) match = re.search("uiConfId : '([^']+)'", self.get_urldata()) uiconfid = match.group(1) url = "http://cdnapi.kaltura.com/html5/html5lib/v1.9.7.6/mwEmbedFrame.php?&wid=%s&uiconf_id=%s&entry_id=%s&playerId=%s&forceMobileHTML5=true&urid=1.9.7.6&callback=mwi" % \ (partnerid, uiconfid, entryid, uniq) data = get_http_data(url) match = re.search(r"mwi\(({.*})\);", data) jsondata = json.loads(match.group(1)) data = jsondata["content"] match = re.search(r"window.kalturaIframePackageData = ({.*});", data) jsondata = json.loads(match.group(1)) ks = jsondata["enviornmentConfig"]["ks"] if options.output_auto: name = jsondata["entryResult"]["meta"]["name"] directory = os.path.dirname(options.output) options.service = "disney" title = "%s-%s" % (name, options.service) title = filenamify(title) if len(directory): options.output = "%s/%s" % (directory, title) else: options.output = title url = "http://cdnapi.kaltura.com/p/%s/sp/%s00/playManifest/entryId/%s/format/applehttp/protocol/http/a.m3u8?ks=%s&referrer=aHR0cDovL3d3dy5kaXNuZXkuc2U=&" % ( partnerid[1:], partnerid[1:], entryid, ks) redirect = check_redirect(url) streams = hlsparse(redirect) for n in list(streams.keys()): yield HLS(copy.copy(options), streams[n], n)
def get(self, options): match = re.search(r"RP.vcdData = ({.*});</script>", self.get_urldata()) if match: data = json.loads(match.group(1)) for i in list(data["station"]["streams"].keys()): yield HTTP(copy.copy(options), data["station"]["streams"][i], i) else: log.error("Can't find stream info") sys.exit(2)
def download(self): if self.options.live and not self.options.force: raise LiveHLSException(self.url) cookies = self.kwargs["cookies"] m3u8 = self.http.request("get", self.url, cookies=cookies).text globaldata, files = parsem3u(m3u8) encrypted = False key = None if "KEY" in globaldata: keydata = globaldata["KEY"] encrypted = True if encrypted: try: from Crypto.Cipher import AES except ImportError: log.error( "You need to install pycrypto to download encrypted HLS streams" ) sys.exit(2) match = re.search(r'URI="(https?://.*?)"', keydata) key = self.http.request("get", match.group(1)).content rand = os.urandom(16) decryptor = AES.new(key, AES.MODE_CBC, rand) file_d = output(self.options, "ts") if hasattr(file_d, "read") is False: return n = 1 eta = ETA(len(files)) for i in files: item = _get_full_url(i[0], self.url) if self.options.output != "-" and not self.options.silent: eta.increment() progressbar(len(files), n, ''.join(['ETA: ', str(eta)])) n += 1 data = self.http.request("get", item, cookies=cookies) if data.status_code == 404: break data = data.content if encrypted: data = decryptor.decrypt(data) file_d.write(data) if self.options.output != "-": file_d.close() if not self.options.silent: progress_stream.write('\n') self.finished = True
def find_all_episodes(self, options): match = re.search( r'<link rel="alternate" type="application/rss\+xml" [^>]*href="([^"]+)"', self.get_urldata()) if match is None: log.error("Couldn't retrieve episode list") sys.exit(2) url = "http://urplay.se%s" % match.group(1).replace("&", "&") xml = ET.XML(get_http_data(url)) return sorted(x.text for x in xml.findall(".//item/link"))