added task queue (django rq) & removes all files when the model is deleted
This commit is contained in:
parent
3564fcc360
commit
9e976e06fd
6 changed files with 90 additions and 24 deletions
|
|
@ -1,4 +1,18 @@
|
|||
asgiref==3.8.1
|
||||
click==8.1.7
|
||||
Django==5.0.7
|
||||
django-cors-headers==4.4.0
|
||||
django-debug-toolbar==4.4.6
|
||||
django-redis==5.4.0
|
||||
django-rq==2.10.2
|
||||
djangorestframework==3.15.2
|
||||
ffmpeg-python==0.2.0
|
||||
future==1.0.0
|
||||
imageio-ffmpeg==0.5.1
|
||||
numpy==2.0.1
|
||||
pillow==10.4.0
|
||||
psutil==6.0.0
|
||||
redis==5.0.8
|
||||
rq==1.16.2
|
||||
setuptools==72.1.0
|
||||
sqlparse==0.5.1
|
||||
|
|
@ -6,8 +6,8 @@ class Video(models.Model):
|
|||
title = models.CharField(max_length=80)
|
||||
description = models.CharField(max_length=500)
|
||||
film_genre = models.CharField(max_length=50, blank=True, null=True)
|
||||
video_file = models.FileField(upload_to='videos', blank=True, null=True)
|
||||
thumbnail = models.FileField(upload_to='img', null=True, blank=True)
|
||||
video_file = models.FileField(upload_to='videos/', blank=True, null=True)
|
||||
thumbnail = models.ImageField(upload_to='thumbnails/', blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
from .models import Video
|
||||
from content.tasks import convert_video, create_thumbnail
|
||||
from content.tasks import convert_video, create_thumbnails
|
||||
from django.dispatch import receiver
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
from django.conf import settings
|
||||
import os
|
||||
import django_rq
|
||||
|
||||
@receiver(post_save, sender=Video)
|
||||
def video_post_save(sender, instance, created, **kwargs):
|
||||
|
|
@ -10,20 +12,58 @@ def video_post_save(sender, instance, created, **kwargs):
|
|||
Generates a thumbnail for a newly created `Video` instance.
|
||||
"""
|
||||
if created:
|
||||
queue = django_rq.get_queue("default", autocommit=True)
|
||||
|
||||
#Convert Video
|
||||
convert_video(instance.video_file.path, "480")
|
||||
convert_video(instance.video_file.path, "720")
|
||||
convert_video(instance.video_file.path, "1080")
|
||||
|
||||
queue.enqueue(convert_video, instance.video_file.path, "480")
|
||||
queue.enqueue(convert_video, instance.video_file.path, "720")
|
||||
queue.enqueue(convert_video, instance.video_file.path, "1080")
|
||||
|
||||
#Create Thumbnail
|
||||
create_thumbnail(instance)
|
||||
|
||||
queue.enqueue(create_thumbnails, instance)
|
||||
|
||||
@receiver(post_delete, sender=Video)
|
||||
def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
Deletes file from filesystem
|
||||
Deletes video file and its converted files from filesystem
|
||||
when corresponding `Video` object is deleted.
|
||||
"""
|
||||
# Delete the original video file
|
||||
if instance.video_file:
|
||||
if os.path.isfile(instance.video_file.path):
|
||||
os.remove(instance.video_file.path)
|
||||
os.remove(instance.video_file.path)
|
||||
|
||||
# Delete the converted videos
|
||||
if instance.video_file:
|
||||
delete_converted_files(instance.video_file.path)
|
||||
|
||||
# Delete the thumbnails
|
||||
if instance.thumbnail:
|
||||
thumbnail_dir = settings.THUMBNAIL_DIR
|
||||
base_filename = os.path.splitext(os.path.basename(instance.video_file.path))[0]
|
||||
thumbnail_1080p_path = os.path.join(thumbnail_dir, base_filename + '_1080p.jpg')
|
||||
thumbnail_480_path = os.path.join(thumbnail_dir, base_filename + '_480p.jpg')
|
||||
|
||||
if os.path.isfile(thumbnail_1080p_path):
|
||||
os.remove(thumbnail_1080p_path)
|
||||
if os.path.isfile(thumbnail_480_path):
|
||||
os.remove(thumbnail_480_path)
|
||||
|
||||
def remove_first_mp4(filename):
|
||||
"""
|
||||
Remove the first .mp4 extension from the filename.
|
||||
"""
|
||||
name_part, ext_part = filename.split('.mp4', 1)
|
||||
new_filename = name_part + ext_part
|
||||
return new_filename
|
||||
|
||||
def delete_converted_files(video_file_path):
|
||||
"""
|
||||
Delete all converted video files related to the original video file.
|
||||
"""
|
||||
resolutions = ["480", "720", "1080"]
|
||||
for resolution in resolutions:
|
||||
converted_video_path = video_file_path + f'_{resolution}p.mp4'
|
||||
converted_video_path = remove_first_mp4(converted_video_path)
|
||||
if os.path.isfile(converted_video_path):
|
||||
os.remove(converted_video_path)
|
||||
|
|
|
|||
|
|
@ -15,27 +15,27 @@ def remove_first_mp4(filename):
|
|||
new_filename = name_part + ext_part
|
||||
return new_filename
|
||||
|
||||
def create_thumbnail(source):
|
||||
video_file_path = source.video_file.path
|
||||
def create_thumbnails(self):
|
||||
video_file_path = self.video_file.path
|
||||
thumbnail_dir = settings.THUMBNAIL_DIR
|
||||
|
||||
base_filename = os.path.splitext(os.path.basename(video_file_path))[0]
|
||||
thumbnail_1920_filename = base_filename + '_1920p.jpg'
|
||||
thumbnail_1920_path = os.path.join(thumbnail_dir, thumbnail_1920_filename)
|
||||
thumbnail_1080p_filename = base_filename + '_1080p.jpg'
|
||||
thumbnail_1080p_path = os.path.join(thumbnail_dir, thumbnail_1080p_filename)
|
||||
thumbnail_480_filename = base_filename + '_480p.jpg'
|
||||
thumbnail_480_path = os.path.join(thumbnail_dir, thumbnail_480_filename)
|
||||
|
||||
thumbnail_path = os.path.join(thumbnail_dir, base_filename + ".jpg")
|
||||
|
||||
if not os.path.exists(thumbnail_dir):
|
||||
os.makedirs(thumbnail_dir)
|
||||
|
||||
try:
|
||||
ffmpeg.input(video_file_path, ss=1).output(thumbnail_1920_path, vf='scale=1920:-1', vframes=1).run(overwrite_output=True)
|
||||
ffmpeg.input(video_file_path, ss=1).output(thumbnail_480_path, vf='scale=480:-1', vframes=1).run(overwrite_output=True)
|
||||
ffmpeg.input(video_file_path, ss=1).output(thumbnail_1080p_path, vf='scale=1920:-1', vframes=1).run(overwrite_output=True)
|
||||
ffmpeg.input(video_file_path, ss=1).output(thumbnail_480_path, vf='scale=720:-1', vframes=1).run(overwrite_output=True)
|
||||
|
||||
source.thumbnail_1920 = os.path.relpath(thumbnail_1920_path, start=settings.MEDIA_ROOT)
|
||||
source.thumbnail_480 = os.path.relpath(thumbnail_480_path, start=settings.MEDIA_ROOT)
|
||||
|
||||
source.save()
|
||||
# Hier speichern wir nur das Thumbnail für die Vorschau im Modell
|
||||
self.thumbnail = os.path.relpath(thumbnail_path, start=settings.MEDIA_ROOT)
|
||||
self.save()
|
||||
|
||||
except ffmpeg._run.Error as e:
|
||||
print(f"Ein Fehler ist aufgetreten: {e.stderr.decode()}")
|
||||
|
|
@ -52,6 +52,7 @@ INSTALLED_APPS = [
|
|||
'rest_framework',
|
||||
'corsheaders',
|
||||
'debug_toolbar',
|
||||
'django_rq',
|
||||
'content.apps.ContentConfig',
|
||||
'users',
|
||||
]
|
||||
|
|
@ -102,10 +103,20 @@ INTERNAL_IPS = [
|
|||
'127.0.0.1',
|
||||
]
|
||||
|
||||
RQ_QUEUES = {
|
||||
'default': {
|
||||
'HOST': 'localhost',
|
||||
'PORT': 6379,
|
||||
'DB': 0,
|
||||
'PASSWORD': 'foobared',
|
||||
'DEFAULT_TIMEOUT': 360,
|
||||
}
|
||||
}
|
||||
|
||||
CACHE_TTL = 60 * 15
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
THUMBNAIL_DIR = os.path.join(BASE_DIR, 'media/img')
|
||||
THUMBNAIL_DIR = os.path.join(BASE_DIR, 'media/thumbnails')
|
||||
MEDIA_URL = '/media/'
|
||||
|
||||
WSGI_APPLICATION = 'videoflix.wsgi.application'
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ Including another URLconf
|
|||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.urls import path, include
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from users import views as user_views
|
||||
|
|
@ -32,6 +32,7 @@ from debug_toolbar.toolbar import debug_toolbar_urls
|
|||
|
||||
urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('django-rq/', include('django_rq.urls')),
|
||||
|
||||
# Content URLs
|
||||
path('content/', content_views.video_list),
|
||||
|
|
|
|||
Loading…
Reference in a new issue