add option at source level to copy over thumbnails with media, resolves #8

This commit is contained in:
meeb 2020-12-18 12:51:04 +11:00
parent ffe0049bab
commit 83b9c167a9
5 changed files with 50 additions and 9 deletions

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.4 on 2020-12-18 01:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('sync', '0002_auto_20201213_0817'),
]
operations = [
migrations.AddField(
model_name='source',
name='copy_thumbnails',
field=models.BooleanField(default=False, help_text='Copy thumbnails with the media, these may be detected and used by some media servers', verbose_name='copy thumbnails'),
),
]

View File

@ -234,6 +234,11 @@ class Source(models.Model):
default=FALLBACK_NEXT_BEST_HD, default=FALLBACK_NEXT_BEST_HD,
help_text=_('What do do when media in your source resolution and codecs is not available') help_text=_('What do do when media in your source resolution and codecs is not available')
) )
copy_thumbnails = models.BooleanField(
_('copy thumbnails'),
default=False,
help_text=_('Copy thumbnails with the media, these may be detected and used by some media servers')
)
has_failed = models.BooleanField( has_failed = models.BooleanField(
_('has failed'), _('has failed'),
default=False, default=False,

View File

@ -150,8 +150,15 @@ def media_pre_delete(sender, instance, **kwargs):
delete_file(instance.thumb.path) delete_file(instance.thumb.path)
# Delete the media file if it exists # Delete the media file if it exists
if instance.media_file: if instance.media_file:
log.info(f'Deleting media for: {instance} path: {instance.media_file.path}') filepath = instance.media_file.path
log.info(f'Deleting media for: {instance} path: {filepath}')
delete_file(instance.media_file.path) delete_file(instance.media_file.path)
# Delete thumbnail copy if it exists
barefilepath, fileext = os.path.splitext(filepath)
thumbpath = f'{barefilepath}.jpg'
log.info(f'Copying thumbnail: {instance} path: {thumbpath}')
delete_file(thumbpath)
@receiver(post_delete, sender=Media) @receiver(post_delete, sender=Media)
def media_post_delete(sender, instance, **kwargs): def media_post_delete(sender, instance, **kwargs):

View File

@ -11,6 +11,7 @@ import uuid
from io import BytesIO from io import BytesIO
from hashlib import sha1 from hashlib import sha1
from datetime import timedelta from datetime import timedelta
from shutil import copyfile
from PIL import Image from PIL import Image
from django.conf import settings from django.conf import settings
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
@ -242,7 +243,7 @@ def download_media_thumbnail(media_id, url):
f'{width}x{height}: {url}') f'{width}x{height}: {url}')
i = resize_image_to_height(i, width, height) i = resize_image_to_height(i, width, height)
image_file = BytesIO() image_file = BytesIO()
i.save(image_file, 'JPEG', quality=80, optimize=True, progressive=True) i.save(image_file, 'JPEG', quality=85, optimize=True, progressive=True)
image_file.seek(0) image_file.seek(0)
media.thumb.save( media.thumb.save(
'thumb', 'thumb',
@ -272,17 +273,18 @@ def download_media(media_id):
log.warn(f'Download task triggeredd media: {media} (UUID: {media.pk}) but it ' log.warn(f'Download task triggeredd media: {media} (UUID: {media.pk}) but it '
f'is now marked to be skipped, not downloading') f'is now marked to be skipped, not downloading')
return return
log.info(f'Downloading media: {media} (UUID: {media.pk}) to: "{media.filepath}"') filepath = media.filepath
log.info(f'Downloading media: {media} (UUID: {media.pk}) to: "{filepath}"')
format_str, container = media.download_media() format_str, container = media.download_media()
if os.path.exists(media.filepath): if os.path.exists(filepath):
# Media has been downloaded successfully # Media has been downloaded successfully
log.info(f'Successfully downloaded media: {media} (UUID: {media.pk}) to: ' log.info(f'Successfully downloaded media: {media} (UUID: {media.pk}) to: '
f'"{media.filepath}"') f'"{filepath}"')
# Link the media file to the object and update info about the download # Link the media file to the object and update info about the download
media.media_file.name = str(media.filepath) media.media_file.name = str(filepath)
media.downloaded = True media.downloaded = True
media.download_date = timezone.now() media.download_date = timezone.now()
media.downloaded_filesize = os.path.getsize(media.filepath) media.downloaded_filesize = os.path.getsize(filepath)
media.downloaded_container = container media.downloaded_container = container
if '+' in format_str: if '+' in format_str:
# Seperate audio and video streams # Seperate audio and video streams
@ -313,6 +315,13 @@ def download_media(media_id):
else: else:
media.downloaded_format = 'audio' media.downloaded_format = 'audio'
media.save() media.save()
# If selected, copy the thumbnail over as well
if media.source.copy_thumbnails and media.thumb:
barefilepath, fileext = os.path.splitext(filepath)
thumbpath = f'{barefilepath}.jpg'
log.info(f'Copying media thumbnail from: {media.thumb.path} '
f'to: {thumbpath}')
copyfile(media.thumb.path, thumbpath)
# Schedule a task to update media servers # Schedule a task to update media servers
for mediaserver in MediaServer.objects.all(): for mediaserver in MediaServer.objects.all():
log.info(f'Scheduling media server updates') log.info(f'Scheduling media server updates')

View File

@ -254,7 +254,8 @@ class AddSourceView(CreateView):
model = Source model = Source
fields = ('source_type', 'key', 'name', 'directory', 'index_schedule', fields = ('source_type', 'key', 'name', 'directory', 'index_schedule',
'delete_old_media', 'days_to_keep', 'source_resolution', 'source_vcodec', 'delete_old_media', 'days_to_keep', 'source_resolution', 'source_vcodec',
'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback') 'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback',
'copy_thumbnails')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.prepopulated_data = {} self.prepopulated_data = {}
@ -325,7 +326,8 @@ class UpdateSourceView(UpdateView):
model = Source model = Source
fields = ('source_type', 'key', 'name', 'directory', 'index_schedule', fields = ('source_type', 'key', 'name', 'directory', 'index_schedule',
'delete_old_media', 'days_to_keep', 'source_resolution', 'source_vcodec', 'delete_old_media', 'days_to_keep', 'source_resolution', 'source_vcodec',
'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback') 'source_acodec', 'prefer_60fps', 'prefer_hdr', 'fallback',
'copy_thumbnails')
def get_success_url(self): def get_success_url(self):
url = reverse_lazy('sync:source', kwargs={'pk': self.object.pk}) url = reverse_lazy('sync:source', kwargs={'pk': self.object.pk})