check whether the uploaded videos are available in the resolution
This commit is contained in:
parent
012161a316
commit
a93e225872
8 changed files with 140 additions and 4 deletions
|
|
@ -7,7 +7,10 @@ from .models import Video
|
|||
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
||||
from django.views.decorators.cache import cache_page
|
||||
from django.conf import settings
|
||||
from django.http import FileResponse, Http404
|
||||
from rest_framework.parsers import MultiPartParser, FormParser
|
||||
from django.http import JsonResponse
|
||||
import os
|
||||
|
||||
CACHETTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
|
||||
|
||||
|
|
@ -23,6 +26,29 @@ def video_list(request):
|
|||
serializer = VideoSerializer(videos, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
@api_view(['GET'])
|
||||
@permission_classes([IsAuthenticated])
|
||||
def check_video(request, id):
|
||||
"""
|
||||
Check if a specific video exists in 480p, 720p, and 1080p resolutions
|
||||
URL: /content/movie/<video_id>/
|
||||
"""
|
||||
resolutions = ['480', '720', '1080']
|
||||
result = {}
|
||||
|
||||
try:
|
||||
video = Video.objects.get(id=id)
|
||||
except Video.DoesNotExist:
|
||||
return JsonResponse({'error': 'Video not found'}, status=404)
|
||||
|
||||
video_dir = os.path.join(settings.MEDIA_ROOT, 'videos', str(id))
|
||||
|
||||
for res in resolutions:
|
||||
video_file_name = f"{video.file_name}_{res}p.m3u8"
|
||||
video_file_path = os.path.join(video_dir, video_file_name)
|
||||
result[res] = os.path.exists(video_file_path)
|
||||
|
||||
return JsonResponse(result)
|
||||
@api_view(['POST'])
|
||||
@permission_classes([IsAuthenticated])
|
||||
def video_upload(request):
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ urlpatterns = [
|
|||
# Content URLs
|
||||
path('content/', content_views.video_list),
|
||||
path('content/upload/', content_views.video_upload),
|
||||
path('content/movie/<int:id>/', content_views.check_video),
|
||||
|
||||
# Users URLs
|
||||
path('users/', user_views.user_list),
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
<app-hero-banner
|
||||
[currentMovie]="currentMovie"
|
||||
(playMovie)="playVideo($event)"
|
||||
(movieIsUploadedChange)="onMovieIsUploadedChange($event)"
|
||||
></app-hero-banner>
|
||||
<app-categories
|
||||
[movies]="movies"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import {
|
||||
Component,
|
||||
EventEmitter,
|
||||
OnChanges,
|
||||
OnInit,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { HeaderComponent } from '../../../shared/components/header/header.component';
|
||||
|
|
@ -37,6 +39,11 @@ export class BrowseComponent implements OnInit {
|
|||
playMovie: string = '';
|
||||
uploadMovieOverview: boolean = false;
|
||||
currentResolution: '480p' | '720p' | '1080p' = '720p';
|
||||
movieIsUploaded: { [resolution: string]: boolean } = {
|
||||
'480': false,
|
||||
'720': false,
|
||||
'1080': false,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private authService: AuthService,
|
||||
|
|
@ -48,6 +55,10 @@ export class BrowseComponent implements OnInit {
|
|||
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
|
||||
}
|
||||
|
||||
onMovieIsUploadedChange(newStatus: { [resolution: string]: boolean }) {
|
||||
this.movieIsUploaded = newStatus;
|
||||
}
|
||||
|
||||
changeResolution(resolution: '480p' | '720p' | '1080p') {
|
||||
if (this.videoPlayer) {
|
||||
this.videoPlayer.switchResolution(resolution);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
[value]="'Play'"
|
||||
[imgPath]="'play'"
|
||||
[imgReverse]="true"
|
||||
[disabled]="!isAnyResolutionUploaded()"
|
||||
(click)="
|
||||
playMovieId(
|
||||
environmentBaseUrl +
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import {
|
|||
EventEmitter,
|
||||
Input,
|
||||
Output,
|
||||
SimpleChanges,
|
||||
} from '@angular/core';
|
||||
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
|
||||
import { MovieService } from '../../../../services/movie.service';
|
||||
|
|
@ -20,11 +21,40 @@ import { environment } from '../../../../environments/environment';
|
|||
export class HeroBannerComponent {
|
||||
@Input() currentMovie: any[] = [];
|
||||
@Output() playMovie = new EventEmitter<string>();
|
||||
@Output() movieIsUploadedChange = new EventEmitter<{
|
||||
[resolution: string]: boolean;
|
||||
}>();
|
||||
|
||||
environmentBaseUrl: string = environment.baseUrl;
|
||||
|
||||
movieIsUploaded: { [resolution: string]: boolean } = {
|
||||
'480': false,
|
||||
'720': false,
|
||||
'1080': false,
|
||||
};
|
||||
constructor(private el: ElementRef, private movieService: MovieService) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
if (changes['currentMovie'] && this.currentMovie.length > 0) {
|
||||
const movieId = this.currentMovie[0]?.id;
|
||||
if (movieId) {
|
||||
this.movieService
|
||||
.isMovieResolutionUploaded(movieId)
|
||||
.subscribe((resolutions) => {
|
||||
this.movieIsUploaded = resolutions;
|
||||
this.movieIsUploadedChange.emit(this.movieIsUploaded);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isAnyResolutionUploaded(): boolean {
|
||||
return (
|
||||
this.movieIsUploaded['480'] ||
|
||||
this.movieIsUploaded['720'] ||
|
||||
this.movieIsUploaded['1080']
|
||||
);
|
||||
}
|
||||
|
||||
playMovieId(videoPath: string) {
|
||||
this.playMovie.emit(videoPath);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
export const environment = {
|
||||
// Development
|
||||
// baseUrl: 'http://127.0.0.1:8000',
|
||||
baseUrl: 'http://127.0.0.1:8000',
|
||||
|
||||
// Live
|
||||
baseUrl: 'https://videoflix-django.andre-kempf.com',
|
||||
// baseUrl: 'https://videoflix-django.andre-kempf.com',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { lastValueFrom, Observable, of } from 'rxjs';
|
||||
import { BehaviorSubject, lastValueFrom, Observable, of } from 'rxjs';
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class MovieService {
|
||||
private movieCache: { [key: number]: { [resolution: string]: boolean } } = {};
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getAllMovies(): Promise<any> {
|
||||
|
|
@ -36,4 +38,68 @@ export class MovieService {
|
|||
Authorization: `Token ${authToken}`,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a movie is uploaded in multiple resolutions.
|
||||
*
|
||||
* @param {number} videoID - The ID of the movie to check.
|
||||
* @returns {Observable<{ [resolution: string]: boolean }>} Observable emitting an object with the availability of each resolution.
|
||||
*/
|
||||
isMovieResolutionUploaded(
|
||||
videoID: number
|
||||
): Observable<{ [resolution: string]: boolean }> {
|
||||
if (this.movieCache.hasOwnProperty(videoID)) {
|
||||
const cachedResolutions = this.movieCache[videoID];
|
||||
|
||||
const missingResolutions = Object.keys(cachedResolutions).filter(
|
||||
(res) => !cachedResolutions[res]
|
||||
);
|
||||
|
||||
if (missingResolutions.length === 0) {
|
||||
return new BehaviorSubject(cachedResolutions).asObservable();
|
||||
} else {
|
||||
return this.fetchAndCacheResolutions(videoID);
|
||||
}
|
||||
} else {
|
||||
return this.fetchAndCacheResolutions(videoID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the availability of multiple resolutions for a specific movie.
|
||||
*
|
||||
* @param {number} videoID - The ID of the movie to fetch resolutions for.
|
||||
* @returns {Observable<{ [resolution: string]: boolean }>} Observable emitting an object with the availability of each resolution.
|
||||
*/
|
||||
private fetchAndCacheResolutions(
|
||||
videoID: number
|
||||
): Observable<{ [resolution: string]: boolean }> {
|
||||
const url = `${environment.baseUrl}/content/movie/${videoID}/`;
|
||||
const headers = this.getAuthHeaders();
|
||||
|
||||
return new Observable<{ [resolution: string]: boolean }>((observer) => {
|
||||
this.http.get(url, { headers }).subscribe(
|
||||
(response: any) => {
|
||||
const resolutions = {
|
||||
'480': response['480'] || false,
|
||||
'720': response['720'] || false,
|
||||
'1080': response['1080'] || false,
|
||||
};
|
||||
this.movieCache[videoID] = resolutions;
|
||||
observer.next(resolutions);
|
||||
observer.complete();
|
||||
},
|
||||
(error) => {
|
||||
observer.next(
|
||||
this.movieCache[videoID] || {
|
||||
'480': false,
|
||||
'720': false,
|
||||
'1080': false,
|
||||
}
|
||||
);
|
||||
observer.complete();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue