From 53ede96df3abdd508ec79347e7f40946b29de313 Mon Sep 17 00:00:00 2001 From: dave Date: Sat, 21 Aug 2021 21:29:58 -0700 Subject: [PATCH] video thumbs --- photoapp/thumbserver.py | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/photoapp/thumbserver.py b/photoapp/thumbserver.py index 1e36a71..d24ca82 100644 --- a/photoapp/thumbserver.py +++ b/photoapp/thumbserver.py @@ -17,14 +17,11 @@ from photoapp.types import User, Photo from photoapp.utils import require_auth from photoapp.common import pwhash from photoapp.dbsession import DatabaseSession -from photoapp.thumb import ThumbGenerator +from photoapp.thumb import thumb_path, image_file_style def get_video_thumb(srcpath, outpath): - #TODO - # download the video file - # use `ffmpeg -i filename.flv` to inspect the video, parse output for duration - # take a thumb halfway through the video + #TODO limit execution time cmd = [ "ffmpeg", @@ -36,6 +33,7 @@ def get_video_thumb(srcpath, outpath): outpath ] + #TODO capture output and only log on error check_call(cmd) @@ -56,13 +54,17 @@ class ThumbWorker(Thread): self.engine = engine self.library = library self.cache = cache - self.thumbtool = thumbtool def run(self): + logged_empty = False while True: try: image_uuid, style_name = self.queue.get(block=True, timeout=5.0) + logged_empty = False except Empty: + if not logged_empty: + logging.info("queue empty") + logged_empty = True continue try: @@ -73,6 +75,10 @@ class ThumbWorker(Thread): self.do_thumb(image_uuid, style_name, s, d) except: traceback.print_exc() #TODO something like _failed_thumbs_cache + #TODO handle errors differently, like + # db error -> kill program + # filesystem error -> kill program + # PIL error -> ignore def do_thumb(self, image_uuid, style_name, session, tmpdir): """ @@ -85,9 +91,14 @@ class ThumbWorker(Thread): logging.info("attempted invalid uuid: %s", image_uuid) return + # Bail if it exists in storage already + cache_path = thumb_path(style_name, image_uuid) + if self.cache.exists(cache_path): + return + # download the image local_src_path = os.path.join(tmpdir, image.fname) # TODO fname isn't sanitized? - thumb_path = os.path.join(tmpdir, "thumb.jpg") + thumb_tmp_path = os.path.join(tmpdir, "thumb.jpg") with ( self.library.open(image.path, "rb") as src, open(local_src_path, "wb") as dest, @@ -95,12 +106,20 @@ class ThumbWorker(Thread): shutil.copyfileobj(src, dest) # generate a still from the image - get_video_thumb(local_src_path, thumb_path) + get_video_thumb(local_src_path, thumb_tmp_path) + + logging.info("generated %s: %sb", thumb_tmp_path, str(os.path.getsize(thumb_tmp_path))) + + # Do normal cropping of the thumb + thumb_cropped_path = os.path.join(tmpdir, "thumb_cropped.jpg") + image_file_style(thumb_tmp_path, thumb_cropped_path, style_name, image.orientation) # copy thumbnail to cache storage - - # TODO write thumb.jpg to thumb storage - os.system(f"cp {thumb_path} /Users/dave/Desktop/") + with ( + open(thumb_cropped_path, 'rb') as fsrc, + closing(self.cache.open(cache_path, 'wb')) as fdest + ): + copyfileobj(fsrc, fdest) class ThumbServiceWeb(object):