X-Git-Url: https://code.delx.au/youtube-cgi/blobdiff_plain/a02f6a351646aa37180db5c4cc4e4d107db7ef7e..0872bf6ff47e5817a748dfcf4c8acaa077f29801:/youtube.cgi diff --git a/youtube.cgi b/youtube.cgi index 409b025..8b103be 100755 --- a/youtube.cgi +++ b/youtube.cgi @@ -79,14 +79,27 @@ cookiejar = cookielib.CookieJar() urlopener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookiejar)) referrer = "" -def urlopen(url): +def urlopen(url, offset=None): global referrer req = urllib2.Request(url) if referrer: req.add_header("Referer", referrer) referrer = url + req.add_header("User-Agent", USER_AGENT) - return urlopener.open(req) + + if offset: + req.add_header("Range", "bytes=%d-" % offset) + + res = urlopener.open(req) + + content_range = res.info().getheader("Content-Range") + if content_range: + tokens = content_range.split() + assert tokens[0] == "bytes" + start = int(tokens[1].split("-")[0]) + assert start == offset + return res def parse_url(url): f = urlopen(url) @@ -215,14 +228,23 @@ def cgimain(): ) return -def copy_with_progress(total_size, infile, outfile): - def pp_size(size): - suffixes = ["", "KiB", "MiB", "GiB"] - for i, suffix in enumerate(suffixes): - if size < 1024: - break - size /= 1024 - return "%.2f %s" % (size, suffix) +def pp_size(size): + suffixes = ["", "KiB", "MiB", "GiB"] + for i, suffix in enumerate(suffixes): + if size < 1024: + break + size /= 1024 + return "%.2f %s" % (size, suffix) + +def copy_with_progress(content_length, infile, outfile): + def print_status(): + sys.stdout.write("\33[2K\r") + sys.stdout.write("%s / %s (%s/sec)" % ( + pp_size(bytes_read), + pp_size(content_length), + pp_size(bytes_read / (now - start_ts)), + )) + sys.stdout.flush() start_ts = time.time() last_ts = 0 @@ -231,13 +253,7 @@ def copy_with_progress(total_size, infile, outfile): now = time.time() if now - last_ts > 0.5: last_ts = now - sys.stdout.write("\33[2K\r") - sys.stdout.write("%s / %s (%s/sec)" % ( - pp_size(bytes_read), - pp_size(total_size), - pp_size(bytes_read / (now - start_ts)), - )) - sys.stdout.flush() + print_status() buf = infile.read(32768) if not buf: @@ -246,6 +262,7 @@ def copy_with_progress(total_size, infile, outfile): bytes_read += len(buf) # Newline at the end + print_status() print def main(): @@ -254,14 +271,46 @@ def main(): except: print >>sys.stderr, "Usage: %s http://youtube.com/watch?v=FOOBAR" % sys.argv[0] sys.exit(1) + doc = parse_url(url) video_url, filename = get_video_url(doc) - video_data = urlopen(video_url) - outfile = open(filename, "w") - total_size = int(video_data.info().getheader("Content-Length")) print "Downloading", filename.encode("utf-8") - copy_with_progress(total_size, video_data, outfile) - video_data.close() + + outfile = open(filename, "a") + offset = outfile.tell() + if offset > 0: + print "Resuming download from", pp_size(offset) + total_size = None + + while True: + try: + video_data = urlopen(video_url, offset) + except urllib2.HTTPError, e: + if e.code == 416: + print "File is complete!" + break + else: + raise + + content_length = int(video_data.info().getheader("Content-Length")) + if total_size is None: + total_size = content_length + + try: + copy_with_progress(content_length, video_data, outfile) + except IOError, e: + print + + video_data.close() + if outfile.tell() != total_size: + old_offset = offset + offset = outfile.tell() + if old_offset == offset: + time.sleep(1) + print "Restarting download from", pp_size(offset) + else: + break + outfile.close()