implement video thumbnail generation and display in movie banner
This commit is contained in:
parent
6f7c9d149b
commit
20a399b5c7
4 changed files with 73 additions and 13 deletions
|
|
@ -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}")
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ section {
|
|||
}
|
||||
}
|
||||
|
||||
.video-banner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.content {
|
||||
position: absolute;
|
||||
width: 60%;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue