From 1985849140f39f5bc28534663cebb50c57f329c2 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Sat, 2 May 2020 13:24:31 +0200 Subject: [PATCH] Added giraffesteal --- giraffesteal/__init__.py | 136 +++++++++++++++++++++++++++++++++++++++ handler.py | 8 ++- youtubesteal/__init__.py | 39 ++++++++--- 3 files changed, 171 insertions(+), 12 deletions(-) create mode 100644 giraffesteal/__init__.py diff --git a/giraffesteal/__init__.py b/giraffesteal/__init__.py new file mode 100644 index 0000000..806b1e8 --- /dev/null +++ b/giraffesteal/__init__.py @@ -0,0 +1,136 @@ +import PIL.Image +import urllib.request +import io +import math +import subprocess +import tempfile +import pathlib +import os +from stitching import tiles_to_equirectangular_blender, multistitch + +def giraffe_normalize(url): + ''' + Takes the URL of any image in a Giraffe360 panorama and returns a string + with substitutable variables for image IDs. + + :param url: URL of an image contained in a Giraffe360 panorama + :return: string with substitutable variables or False if URL invalid + ''' + + try: + with urllib.request.urlopen(url) as res: + assert res.getcode() == 200 + + parts = url.split("/") + + assert "_" in parts[-1] + assert parts[-1][0] == "l" + + parts[-1] = "l%i_%s_%s_%s.jpg" + + return "/".join(parts) + + except: + return False + +def giraffe_getmaxzoom(schema): + ''' + Takes a normalized string from giraffe_normalize() and returns the maximum + zoom level available. + + :param schema: normalized URL format output by giraffe_normalize() + :return: int value of largest available zoom level + ''' + + l = 0 + + while True: + try: + url = schema % (l+1, "f", "01", "01") + with urllib.request.urlopen(url) as res: + assert res.getcode() == 200 + l += 1 + except: + return l + +def giraffe_export(schema): + ''' + Takes a normalized string from giraffe_normalize() and returns a list of + lists of lists containing all images fit for passing into stitch(). + + :param schema: normalized URL format output by giraffe_normalize() + :return: list of lists of lists of PIL.Image() objects for multistitch() + ''' + + maxzoom = giraffe_getmaxzoom(schema) + output = [] + + for tile in "frblud": + t_array = [] + y = 1 + + while True: + r_array = [] + x = 1 + + while True: + try: + res = urllib.request.urlopen(schema % (maxzoom, tile, str(y).zfill(2), str(x).zfill(2))) + assert res.getcode() == 200 + fo = io.BytesIO(res.read()) + img = PIL.Image.open(fo) + r_array.append(img) + x += 1 + except urllib.error.HTTPError: + break + except Exception: + raise + + if not r_array: + break + + t_array.append(r_array) + y += 1 + + output.append(t_array) + + return output + +def giraffe_make_tiles(url): + ''' + Determines the type of processing needed to build the six tiles, then + creates and returns them. + + :param urL: URL of any image in a Giraffe360 panorama + :return: list of stitched PIL.Image objects (back, right, front, left, top, + bottom) + ''' + + parts = url.split("/") + + try: + schema = giraffe_normalize(url) + images = giraffe_export(schema) + return multistitch(images) + + except: + raise + raise ValueError("%s does not seem to be a valid Giraffe360 URL." % url) + +def giraffe_to_equirectangular(url, rotation=[0,0,0], resolution=[3840,1920]): + ''' + Takes the URL of any image in a Giraffe360 panorama and returns a finished + stitched image. + + :param url: Image URL + :return: PIL.Image object containing the final image + ''' + + stitched = giraffe_make_tiles(url) + function = tiles_to_equirectangular_blender + + rx, ry, rz = rotation + width, height = resolution + return function(*stitched, rx=rx, ry=ry, rz=rz, width=width, height=height) + +process_url = giraffe_to_equirectangular diff --git a/handler.py b/handler.py index 87a20a1..9499b66 100755 --- a/handler.py +++ b/handler.py @@ -4,12 +4,14 @@ import re import importlib import argparse import subprocess +import traceback regs = { "\d/\d/\d_\d\.jpg": "krpanosteal", "pano\_[frblud].jpg": "krpanosteal", "my.matterport.com/show/": "matterportsteal", - "youtube.com": "youtubesteal" + "youtube.com": "youtubesteal", + "l\d_[frblud]_\d\d_\d\d.jpg": "giraffesteal" } @@ -52,6 +54,6 @@ if __name__ == "__main__": args.output + "/" + args.title + ".thumb.jpg"]) else: image.save(args.output + "/" + args.title + ".png") - except Exception as e: + except Exception: with open(args.output + "/" + args.title + ".err", "w") as errorfile: - errorfile.write(str(e)) + errorfile.write(traceback.format_exc()) diff --git a/youtubesteal/__init__.py b/youtubesteal/__init__.py index fa1203d..178cf9d 100644 --- a/youtubesteal/__init__.py +++ b/youtubesteal/__init__.py @@ -14,17 +14,38 @@ from stitching import tiles_to_equirectangular_blender, multistitch def youtube_get_video(url): vid = uuid.uuid4().hex - process = subprocess.Popen( - ['youtube-dl', - '--user-agent', '""', - '-o', vid, - url, - ], cwd="/tmp/panosteal/youtube/" - ) + with open("/tmp/" + vid, "w") as logfile: + process = subprocess.Popen( + ['youtube-dl', + '--user-agent', '""', + '-o', vid, + "--merge-output-format", "mkv", + url, + ], + cwd="/tmp/panosteal/youtube/", + stdout=logfile, + stderr=logfile + ) - process.wait() + process.wait() - data = open('/tmp/panosteal/youtube/%s.mkv' % vid, 'rb').read() + try: + data = open('/tmp/panosteal/youtube/%s.mkv' % vid, 'rb').read() + except: + try: + data = open('/tmp/panosteal/youtube/%s.mp4' % vid, 'rb').read() + except: + try: + data = open('/tmp/panosteal/youtube/%s.webm' % vid, 'rb').read() + process2 = subprocess.Popen( + ['ffmpeg', + '-i', '%s.webm' % vid, + '-c:v', "copy", + '%s.mkv' % vid], + cwd="/tmp/panosteal/youtube/" + ) + except: + raise for i in glob.glob("/tmp/panosteal/youtube/%s*" % vid): os.remove(i)