implement video thumbnail generation and display in movie banner

This commit is contained in:
Chneemann 2024-09-05 04:33:40 +02:00
parent 6f7c9d149b
commit 20a399b5c7
4 changed files with 73 additions and 13 deletions

View file

@ -44,7 +44,7 @@ def delete_original_video(source):
def create_thumbnails(instance, model_id):
"""
Creates high-resolution and low-resolution thumbnails from a video file
Creates high-resolution and low-resolution thumbnails from a video file.
"""
video_file_path = instance.video_file.path
thumbnail_dir = os.path.join(settings.THUMBNAIL_DIR, str(model_id))
@ -59,10 +59,32 @@ def create_thumbnails(instance, model_id):
os.makedirs(thumbnail_dir)
try:
# Generate the thumbnails
# Generate the image 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_480_path, vf='scale=720:-1', vframes=1).run(overwrite_output=True)
# Create the 10-second video thumbnail
create_video_thumbnail(video_file_path, thumbnail_dir, base_filename)
except ffmpeg._run.Error as e:
error_message = e.stderr.decode() if e.stderr else "Unknown ffmpeg error"
print(f"Ein Fehler ist aufgetreten: {error_message}")
print(f"An error has occurred: {error_message}")
def create_video_thumbnail(video_file_path, thumbnail_dir, base_filename):
"""
Creates a 10-second video thumbnail from a video file without audio.
"""
video_thumbnail_filename = base_filename + '_video-thumbnail.mp4'
video_thumbnail_path = os.path.join(thumbnail_dir, video_thumbnail_filename)
try:
ffmpeg.input(video_file_path, ss=1, t=10).output(
video_thumbnail_path,
vf='scale=1280:-1',
vcodec='libx264',
an=None # Disable audio
).run(overwrite_output=True)
except ffmpeg._run.Error as e:
error_message = e.stderr.decode() if e.stderr else "Unknown ffmpeg error"
print(f"An error has occurred: {error_message}")

View file

@ -5,21 +5,39 @@
>
<div
class="movie-banner"
[ngStyle]="{
'background-image':
'url(' +
[ngClass]="{
fullVhBanner: !screenWidth
}"
>
<video
#videoElement
*ngIf="currentMovie[0]?.file_name"
[src]="
environmentBaseUrl +
'/media/thumbnails/' +
currentMovie[0]?.id +
'/' +
currentMovie[0]?.file_name +
'_1080p.jpg' +
')',
}"
[ngClass]="{
fullVhBanner: !screenWidth
}"
></div>
'_video-thumbnail.mp4'
"
autoplay
muted
loop
playsinline
class="video-banner"
>
<img
[src]="
environmentBaseUrl +
'/media/thumbnails/' +
currentMovie[0]?.id +
'/' +
currentMovie[0]?.file_name +
'_1080p.jpg'
"
/>
</video>
</div>
@if (currentMovie.length > 0) {
<div
class="content"

View file

@ -31,6 +31,12 @@ section {
}
}
.video-banner {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
position: absolute;
width: 60%;

View file

@ -7,6 +7,7 @@ import {
OnChanges,
Output,
SimpleChanges,
ViewChild,
} from '@angular/core';
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
import { MovieService } from '../../../../services/movie.service';
@ -22,6 +23,7 @@ import { UserService } from '../../../../services/user.service';
styleUrl: './hero-banner.component.scss',
})
export class HeroBannerComponent implements OnChanges {
@ViewChild('videoElement') videoElementRef!: ElementRef<HTMLVideoElement>;
@Input() currentMovie: any[] = [];
@Input() screenWidth: boolean = false;
@Input() favoriteMovies: any[] = [];
@ -44,6 +46,10 @@ export class HeroBannerComponent implements OnChanges {
public userService: UserService
) {}
ngAfterViewInit() {
this.videoSpeed();
}
ngOnChanges(changes: SimpleChanges) {
if (changes['currentMovie'] && this.currentMovie.length > 0) {
const movieId = this.currentMovie[0]?.id;
@ -54,10 +60,18 @@ export class HeroBannerComponent implements OnChanges {
this.movieIsUploaded = resolutions;
this.movieIsUploadedChange.emit(this.movieIsUploaded);
});
setTimeout(() => this.videoSpeed(), 0);
}
}
}
videoSpeed() {
if (this.videoElementRef) {
const videoElement = this.videoElementRef.nativeElement;
videoElement.playbackRate = 0.5;
}
}
toggleLikeMovie(movieId: number): void {
if (this.favoriteMovies.includes(movieId)) {
this.favoriteMovies = this.favoriteMovies.filter((id) => id !== movieId);