diff --git a/svtplay_dl.py b/svtplay_dl.py index 7c8410c..d978e7c 100755 --- a/svtplay_dl.py +++ b/svtplay_dl.py @@ -1,23 +1,8 @@ #!/usr/bin/env python import sys -if sys.version_info > (3, 0): - from urllib.request import Request, urlopen - from urllib.error import HTTPError, URLError - from urllib.parse import urlparse, parse_qs, unquote_plus, quote_plus - from io import BytesIO as StringIO -else: - from urllib2 import Request, urlopen, HTTPError, URLError - from urlparse import urlparse, parse_qs - from urllib import unquote_plus, quote_plus - from StringIO import StringIO - import re import os -import subprocess from optparse import OptionParser -import shlex -import json -import time import logging from svtplay.log import log @@ -73,211 +58,6 @@ class Options: self.hls = False self.other = None -def parsem3u(data): - if not data.startswith("#EXTM3U"): - raise ValueError("Does not apprear to be a ext m3u file") - - files = [] - streaminfo = {} - globdata = {} - - data = data.replace("\r", "\n") - for l in data.split("\n")[1:]: - if not l: - continue - if l.startswith("#EXT-X-STREAM-INF:"): - #not a proper parser - info = [x.strip().split("=", 1) for x in l[18:].split(",")] - streaminfo.update({info[1][0]: info[1][1]}) - elif l.startswith("#EXT-X-ENDLIST"): - break - elif l.startswith("#EXT-X-"): - globdata.update(dict([l[7:].strip().split(":", 1)])) - elif l.startswith("#EXTINF:"): - dur, title = l[8:].strip().split(",", 1) - streaminfo['duration'] = dur - streaminfo['title'] = title - elif l[0] == '#': - pass - else: - files.append((l, streaminfo)) - streaminfo = {} - - return globdata, files - -def progress(byte, total, extra = ""): - """ Print some info about how much we have downloaded """ - ratio = float(byte) / total - percent = round(ratio*100, 2) - tlen = str(len(str(total))) - fmt = "Downloaded %"+tlen+"dkB of %dkB bytes (% 3.2f%%)" - progresstr = fmt % (byte >> 10, total >> 10, percent) - - columns = int(os.getenv("COLUMNS", "80")) - if len(progresstr) < columns - 13: - p = int((columns - len(progresstr) - 3) * ratio) - q = int((columns - len(progresstr) - 3) * (1 - ratio)) - progresstr = "[" + ("#" * p) + (" " * q) + "] " + progresstr - progress_stream.write(progresstr + ' ' + extra + '\r') - - if byte >= total: - progress_stream.write('\n') - - progress_stream.flush() - -def download_hls(options, url, baseurl=None): - data = get_http_data(url) - globaldata, files = parsem3u(data) - streams = {} - for i in files: - streams[int(i[1]["BANDWIDTH"])] = i[0] - - test = select_quality(options, streams) - m3u8 = get_http_data(test) - globaldata, files = parsem3u(m3u8) - encrypted = False - key = None - try: - keydata = globaldata["KEY"] - encrypted = True - except: - pass - - 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("URI=\"(http://.*)\"", keydata) - key = get_http_data(match.group(1)) - rand = os.urandom(16) - decryptor = AES.new(key, AES.MODE_CBC, rand) - n = 1 - if options.output != "-": - extension = re.search("(\.[a-z0-9]+)$", options.output) - if not extension: - options.output = "%s.ts" % options.output - log.info("Outfile: %s", options.output) - file_d = open(options.output, "wb") - else: - file_d = sys.stdout - - start = time.time() - estimated = "" - for i in files: - item = i[0] - if options.output != "-": - progressbar(len(files), n, estimated) - if item[0:5] != "http:": - item = "%s/%s" % (baseurl, item) - data = get_http_data(item) - if encrypted: - lots = StringIO(data) - - plain = b"" - crypt = lots.read(1024) - decrypted = decryptor.decrypt(crypt) - while decrypted: - plain += decrypted - crypt = lots.read(1024) - decrypted = decryptor.decrypt(crypt) - data = plain - - file_d.write(data) - now = time.time() - dt = now - start - et = dt / (n + 1) * len(files) - rt = et - dt - td = timedelta(seconds = int(rt)) - estimated = "Estimated Remaining: " + str(td) - n += 1 - - if options.output != "-": - file_d.close() - progress_stream.write('\n') - -def download_http(options, url): - """ Get the stream from HTTP """ - response = urlopen(url) - total_size = response.info()['Content-Length'] - total_size = int(total_size) - bytes_so_far = 0 - if options.output != "-": - extension = re.search("(\.[a-z0-9]+)$", url) - if extension: - options.output = options.output + extension.group(1) - log.info("Outfile: %s", options.output) - file_d = open(options.output, "wb") - else: - file_d = sys.stdout - - lastprogress = 0 - while 1: - chunk = response.read(8192) - bytes_so_far += len(chunk) - - if not chunk: - break - - file_d.write(chunk) - if options.output != "-": - now = time.time() - if lastprogress + 1 < now: - lastprogress = now - progress(bytes_so_far, total_size) - - if options.output != "-": - file_d.close() - -def download_rtmp(options, url): - """ Get the stream from RTMP """ - args = [] - if options.live: - args.append("-v") - - if options.resume: - args.append("-e") - - extension = re.search("(\.[a-z0-9]+)$", url) - if options.output != "-": - if not extension: - extension = re.search("-y (.+):[-_a-z0-9\/]", options.other) - if not extension: - options.output = "%s.flv" % options.output - else: - options.output = "%s%s" % (options.output, extension.group(1)) - else: - options.output = options.output + extension.group(1) - log.info("Outfile: %s", options.output) - args += ["-o", options.output] - if options.silent or options.output == "-": - args.append("-q") - if options.other: - args += shlex.split(options.other) - command = ["rtmpdump", "-r", url] + args - try: - subprocess.call(command) - except OSError as e: - log.error("Could not execute rtmpdump: " + e.strerror) - -def select_quality(options, streams): - sort = sorted(streams.keys(), key=int) - - if options.quality: - quality = options.quality - else: - quality = sort.pop() - - try: - selected = streams[int(quality)] - except (KeyError, ValueError): - log.error("Can't find that quality. (Try one of: %s)", - ", ".join(map(str, sort))) - sys.exit(4) - - return selected - def get_media(url, options): sites = [Aftonbladet(), Dr(), Expressen(), Hbo(), Justin(), Kanal5(), Kanal9(), Nrk(), Qbrick(), Ruv(), Sr(), Svtplay(), Tv4play(), Urplay(), Viaplay()]