when the thumbnail is created the page is refreshed

This commit is contained in:
Chneemann 2024-08-14 19:21:56 +02:00
parent f20fd0566f
commit 58208d11dd
7 changed files with 97 additions and 41 deletions

View file

@ -9,6 +9,7 @@ class Video(models.Model):
film_genre = models.CharField(max_length=20, choices=FILM_GENRES, blank=True, null=True) film_genre = models.CharField(max_length=20, choices=FILM_GENRES, blank=True, null=True)
video_file = models.FileField(upload_to='videos/', blank=True, null=True) video_file = models.FileField(upload_to='videos/', blank=True, null=True)
file_name = models.CharField(max_length=50, blank=True, null=True) file_name = models.CharField(max_length=50, blank=True, null=True)
thumbnail_created = models.BooleanField(default=False)
def __str__(self): def __str__(self):
return f'({self.id}) {self.title}' return f'({self.id}) {self.title}'

View file

@ -1,5 +1,5 @@
from .models import Video from .models import Video
from .tasks import convert_video_to_hls, create_thumbnails, delete_original_video from .tasks import convert_video_to_hls, create_thumbnails, delete_original_video, update_thumbnail_status
from django.dispatch import receiver from django.dispatch import receiver
from django.db.models.signals import post_save, post_delete from django.db.models.signals import post_save, post_delete
from django.conf import settings from django.conf import settings
@ -16,12 +16,11 @@ def video_post_save(sender, instance, created, **kwargs):
queue = django_rq.get_queue("default", autocommit=True) queue = django_rq.get_queue("default", autocommit=True)
#Create thumbnail #Create thumbnail
queue.enqueue(create_thumbnails, instance, instance.id) create_thumbnails(instance, instance.id)
#Convert video #Convert video
queue.enqueue(convert_video_to_hls, instance.video_file.path, "480", instance.id) for resolution in ["480", "720", "1080"]:
queue.enqueue(convert_video_to_hls, instance.video_file.path, "720", instance.id) queue.enqueue(convert_video_to_hls, instance.video_file.path, resolution, instance.id)
queue.enqueue(convert_video_to_hls, instance.video_file.path, "1080", instance.id)
# Delete the original video file # Delete the original video file
queue.enqueue(delete_original_video, instance.video_file.path) queue.enqueue(delete_original_video, instance.video_file.path)

View file

@ -4,6 +4,7 @@ import ffmpeg
import os import os
from django.conf import settings from django.conf import settings
from .models import Video from .models import Video
from django_rq import get_queue
def convert_video_to_hls(source, resolution, model_id): def convert_video_to_hls(source, resolution, model_id):
target_dir = os.path.join(os.path.dirname(source), str(model_id)) target_dir = os.path.join(os.path.dirname(source), str(model_id))
@ -38,8 +39,8 @@ def delete_original_video(source):
except OSError as e: except OSError as e:
print(f"Error deleting original file: {e}") print(f"Error deleting original file: {e}")
def create_thumbnails(self, model_id): def create_thumbnails(instance, model_id):
video_file_path = self.video_file.path video_file_path = instance.video_file.path
thumbnail_dir = os.path.join(settings.THUMBNAIL_DIR, str(model_id)) thumbnail_dir = os.path.join(settings.THUMBNAIL_DIR, str(model_id))
base_filename = os.path.splitext(os.path.basename(video_file_path))[0] base_filename = os.path.splitext(os.path.basename(video_file_path))[0]
@ -52,8 +53,19 @@ def create_thumbnails(self, model_id):
os.makedirs(thumbnail_dir) os.makedirs(thumbnail_dir)
try: try:
# Generate the thumbnails
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_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) ffmpeg.input(video_file_path, ss=1).output(thumbnail_480_path, vf='scale=720:-1', vframes=1).run(overwrite_output=True)
# Update thumbnail status
update_thumbnail_status(model_id)
except ffmpeg._run.Error as e: except ffmpeg._run.Error as e:
print(f"Ein Fehler ist aufgetreten: {e.stderr.decode()}") print(f"Ein Fehler ist aufgetreten: {e.stderr.decode()}")
def update_thumbnail_status(video_id):
try:
video = Video.objects.get(id=video_id)
video.thumbnail_created = True
video.save()
except Video.DoesNotExist:
print(f"Video with id {video_id} does not exist.")

View file

@ -16,12 +16,25 @@ CACHETTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
#@cache_page(CACHETTL) #@cache_page(CACHETTL)
def video_list(request): def video_list(request):
"""
if request.method == 'GET': List all videos.
video = Video.objects.all() """
serializer = VideoSerializer(video, many=True) videos = Video.objects.all()
serializer = VideoSerializer(videos, many=True)
return Response(serializer.data) return Response(serializer.data)
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def check_thumbnail_status(request, video_id):
"""
Check the status of the thumbnail creation for a specific video.
"""
try:
video = Video.objects.get(id=video_id)
return Response({'thumbnail_created': video.thumbnail_created})
except Video.DoesNotExist:
return Response({'error': 'Video not found'}, status=404)
@api_view(['POST']) @api_view(['POST'])
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
def video_upload(request): def video_upload(request):

View file

@ -37,6 +37,7 @@ urlpatterns = [
# Content URLs # Content URLs
path('content/', content_views.video_list), path('content/', content_views.video_list),
path('content/upload/', content_views.video_upload), path('content/upload/', content_views.video_upload),
path('content/<int:video_id>/status/', content_views.check_thumbnail_status),
# Users URLs # Users URLs
path('users/', user_views.user_list), path('users/', user_views.user_list),

View file

@ -44,27 +44,47 @@ export class UploadMovieComponent {
} }
async onSubmit(ngForm: NgForm) { async onSubmit(ngForm: NgForm) {
if (ngForm.submitted && ngForm.form.valid) { if (!ngForm.submitted || !ngForm.form.valid) return;
const formData = new FormData();
formData.append('title', this.movieData.title); try {
formData.append('description', this.movieData.description); this.movieData.send = true;
formData.append('film_genre', this.movieData.filmGenre);
if (this.movieData.videoFile) { const formData = this.createFormData();
formData.append('video_file', this.movieData.videoFile); const response = await this.movieService
} .uploadMovie(formData)
try { .toPromise();
await this.movieService.uploadMovie(formData); const videoId = response.id;
this.movieData.send = true;
setTimeout(() => { await this.waitForThumbnailCreation(videoId);
ngForm.resetForm();
this.uploadMovieOverview(); ngForm.resetForm();
this.movieData.send = false; this.uploadMovieOverview();
window.location.reload(); this.movieData.send = false;
}, 1000); window.location.reload();
this.errorService.clearError(); this.errorService.clearError();
} catch (error) { } catch (error) {
this.errorService.handleError(error); this.errorService.handleError(error);
} }
}
private createFormData(): FormData {
const formData = new FormData();
formData.append('title', this.movieData.title);
formData.append('description', this.movieData.description);
formData.append('film_genre', this.movieData.filmGenre);
if (this.movieData.videoFile) {
formData.append('video_file', this.movieData.videoFile);
}
return formData;
}
private async waitForThumbnailCreation(videoId: number) {
while (true) {
const statusResponse = await this.movieService
.checkThumbnailStatus(videoId)
.toPromise();
if (statusResponse?.thumbnail_created) break;
await new Promise((resolve) => setTimeout(resolve, 2000));
} }
} }
} }

View file

@ -21,12 +21,22 @@ export class MovieService {
return lastValueFrom(this.http.get(url, { headers })); return lastValueFrom(this.http.get(url, { headers }));
} }
async uploadMovie(formData: FormData) { uploadMovie(formData: FormData): Observable<any> {
const headers = this.getAuthHeaders(); const headers = this.getAuthHeaders();
await lastValueFrom( return this.http.post<any>(
this.http.post(`${environment.baseUrl}/content/upload/`, formData, { `${environment.baseUrl}/content/upload/`,
headers, formData,
}) { headers }
);
}
checkThumbnailStatus(
videoId: number
): Observable<{ thumbnail_created: boolean }> {
const headers = this.getAuthHeaders();
return this.http.get<{ thumbnail_created: boolean }>(
`${environment.baseUrl}/content/${videoId}/status/`,
{ headers }
); );
} }