Simplified thumbnail logic, only the best thumbnail size is downloaded and then it is resized and cropped to an appropriate size for use in the web UI.

This commit is contained in:
2019-08-19 21:05:13 +03:00
parent 2bdafa291d
commit c1473dd163
10 changed files with 82 additions and 33 deletions

View File

@ -6,6 +6,8 @@ import logging
import requests
import mimetypes
import os
import PIL.Image
import PIL.ImageOps
from urllib.parse import urljoin
log = logging.getLogger('downloader')
@ -61,9 +63,9 @@ def downloader_process_all():
downloader_process_subscription(subscription)
def fetch_thumbnail(url, object_type, identifier, quality):
def fetch_thumbnail(url, object_type, identifier, thumb_size):
log.info('Fetching thumbnail url=%s object_type=%s identifier=%s quality=%s', url, object_type, identifier, quality)
log.info('Fetching thumbnail url=%s object_type=%s identifier=%s', url, object_type, identifier)
# Make request to obtain mime type
try:
@ -75,17 +77,28 @@ def fetch_thumbnail(url, object_type, identifier, quality):
ext = mimetypes.guess_extension(response.headers['Content-Type'])
# Build file path
file_name = f"{identifier}-{quality}{ext}"
file_name = f"{identifier}{ext}"
abs_path_dir = os.path.join(srv_settings.MEDIA_ROOT, "thumbs", object_type)
abs_path = os.path.join(abs_path_dir, file_name)
abs_path_tmp = file_name + '.tmp'
# Store image
try:
os.makedirs(abs_path_dir, exist_ok=True)
with open(abs_path, "wb") as f:
with open(abs_path_tmp, "wb") as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
# Resize and crop to thumbnail size
image = PIL.Image.open(abs_path_tmp)
image = PIL.ImageOps.fit(image, thumb_size)
image.save(abs_path)
image.close()
# Delete temp file
os.unlink(abs_path_tmp)
except requests.exceptions.RequestException as e:
log.error('Error while downloading stream for thumbnail %s. Error: %s', url, e)
return url

View File

@ -4,6 +4,7 @@ from threading import Lock
from apscheduler.triggers.cron import CronTrigger
from django.db.models import Max
from django.conf import settings
from YtManagerApp.management.appconfig import appconfig
from YtManagerApp.management.downloader import fetch_thumbnail, downloader_process_subscription
@ -110,21 +111,13 @@ class SynchronizeJob(Job):
self.__new_vids.append(Video.create(item, sub))
def fetch_missing_thumbnails(self, object: Union[Subscription, Video]):
if isinstance(object, Subscription):
object_type = "sub"
object_id = object.playlist_id
else:
object_type = "video"
object_id = object.video_id
if object.icon_default.startswith("http"):
object.icon_default = fetch_thumbnail(object.icon_default, object_type, object_id, 'default')
object.save()
if object.icon_best.startswith("http"):
object.icon_best = fetch_thumbnail(object.icon_best, object_type, object_id, 'best')
object.save()
def fetch_missing_thumbnails(self, obj: Union[Subscription, Video]):
if obj.thumbnail.startswith("http"):
if isinstance(obj, Subscription):
obj.thumbnail = fetch_thumbnail(obj.thumbnail, 'sub', obj.playlist_id, settings.THUMBNAIL_SIZE_SUBSCRIPTION)
elif isinstance(obj, Video):
obj.thumbnail = fetch_thumbnail(obj.thumbnail, 'video', obj.video_id, settings.THUMBNAIL_SIZE_VIDEO)
obj.save()
def check_video_deleted(self, video: Video):
if video.downloaded_path is not None: