bugfixes, clean code, switch vjs player to hls, optimized backend & play video in different resolutions
This commit is contained in:
parent
27232e1421
commit
c686296aeb
22 changed files with 264 additions and 617 deletions
|
|
@ -6,7 +6,9 @@ from import_export.admin import ImportExportModelAdmin
|
||||||
class VideoResource(resources.ModelResource):
|
class VideoResource(resources.ModelResource):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Video
|
model = Video
|
||||||
|
|
||||||
@admin.register(Video)
|
@admin.register(Video)
|
||||||
class VideoAdmin(ImportExportModelAdmin):
|
class VideoAdmin(ImportExportModelAdmin):
|
||||||
pass
|
resource_class = VideoResource
|
||||||
|
readonly_fields = ('file_name',)
|
||||||
|
list_display = ('title', 'file_name', 'created_at')
|
||||||
|
|
@ -15,4 +15,5 @@ FILM_GENRES = [
|
||||||
('musical', 'Musical'),
|
('musical', 'Musical'),
|
||||||
('war', 'War'),
|
('war', 'War'),
|
||||||
('western', 'Western'),
|
('western', 'Western'),
|
||||||
|
('other', 'Miscellaneous'),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from .class_assets import FILM_GENRES
|
from .class_assets import FILM_GENRES
|
||||||
|
import os
|
||||||
class Video(models.Model):
|
class Video(models.Model):
|
||||||
created_at = models.DateField(default=date.today)
|
created_at = models.DateField(default=date.today)
|
||||||
title = models.CharField(max_length=80)
|
title = models.CharField(max_length=80)
|
||||||
|
|
@ -11,4 +11,12 @@ class Video(models.Model):
|
||||||
file_name = models.CharField(max_length=50, blank=True, null=True)
|
file_name = models.CharField(max_length=50, blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'({self.id}) {self.title}'
|
return f'({self.id}) {self.title}'
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if self.video_file and not self.file_name:
|
||||||
|
video_file_path = self.video_file.path
|
||||||
|
base_filename, _ = os.path.splitext(os.path.basename(video_file_path))
|
||||||
|
self.file_name = base_filename
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
@ -15,14 +15,14 @@ def video_post_save(sender, instance, created, **kwargs):
|
||||||
if created:
|
if created:
|
||||||
queue = django_rq.get_queue("default", autocommit=True)
|
queue = django_rq.get_queue("default", autocommit=True)
|
||||||
|
|
||||||
|
#Create thumbnail
|
||||||
|
queue.enqueue(create_thumbnails, instance, instance.id)
|
||||||
|
|
||||||
#Convert video
|
#Convert video
|
||||||
queue.enqueue(convert_video_to_hls, instance.video_file.path, "480", instance.id)
|
queue.enqueue(convert_video_to_hls, instance.video_file.path, "480", instance.id)
|
||||||
queue.enqueue(convert_video_to_hls, instance.video_file.path, "720", instance.id)
|
queue.enqueue(convert_video_to_hls, instance.video_file.path, "720", instance.id)
|
||||||
queue.enqueue(convert_video_to_hls, instance.video_file.path, "1080", instance.id)
|
queue.enqueue(convert_video_to_hls, instance.video_file.path, "1080", instance.id)
|
||||||
|
|
||||||
#Create thumbnail
|
|
||||||
queue.enqueue(create_thumbnails, instance, 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)
|
||||||
|
|
||||||
|
|
@ -33,8 +33,12 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||||
when the corresponding `Video` object is deleted.
|
when the corresponding `Video` object is deleted.
|
||||||
"""
|
"""
|
||||||
main_directory = os.path.dirname(instance.video_file.path)
|
main_directory = os.path.dirname(instance.video_file.path)
|
||||||
|
parent_directory = os.path.dirname(main_directory)
|
||||||
model_directory = os.path.join(main_directory, str(instance.id))
|
model_directory = os.path.join(main_directory, str(instance.id))
|
||||||
|
thumbnail_directory = os.path.join(parent_directory, 'thumbnails', str(instance.id))
|
||||||
|
|
||||||
delete_directory(model_directory)
|
delete_directory(model_directory)
|
||||||
|
delete_directory(thumbnail_directory)
|
||||||
|
|
||||||
def delete_directory(directory_path):
|
def delete_directory(directory_path):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -27,25 +27,8 @@ def convert_video_to_hls(source, resolution, model_id):
|
||||||
f'{target}.m3u8'
|
f'{target}.m3u8'
|
||||||
]
|
]
|
||||||
|
|
||||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
subprocess.run(cmd, capture_output=True, text=True)
|
||||||
if result.returncode == 0:
|
|
||||||
save_converted_file_name(model_id, base_filename)
|
|
||||||
else:
|
|
||||||
print(f"Conversion error: {result.stderr}")
|
|
||||||
|
|
||||||
def save_converted_file_name(model_id, file_name):
|
|
||||||
"""
|
|
||||||
Saves the name of the converted file in the model or a database.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
instance = Video.objects.get(id=model_id)
|
|
||||||
instance.file_name = file_name
|
|
||||||
instance.save()
|
|
||||||
except Video.DoesNotExist:
|
|
||||||
print(f"Model with ID {model_id} not found.")
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error saving file name:: {e}")
|
|
||||||
|
|
||||||
def delete_original_video(source):
|
def delete_original_video(source):
|
||||||
"""
|
"""
|
||||||
Deletes the original MP4 file.
|
Deletes the original MP4 file.
|
||||||
|
|
|
||||||
|
|
@ -7,16 +7,28 @@ from .models import Video
|
||||||
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
from django.core.cache.backends.base import DEFAULT_TIMEOUT
|
||||||
from django.views.decorators.cache import cache_page
|
from django.views.decorators.cache import cache_page
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from rest_framework.parsers import MultiPartParser, FormParser
|
||||||
|
|
||||||
CACHETTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
|
CACHETTL = getattr(settings, 'CACHE_TTL', DEFAULT_TIMEOUT)
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
@api_view(['GET'])
|
@api_view(['GET'])
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
@cache_page(CACHETTL)
|
#@cache_page(CACHETTL)
|
||||||
def video_list(request):
|
def video_list(request):
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
video = Video.objects.all()
|
video = Video.objects.all()
|
||||||
serializer = VideoSerializer(video, many=True)
|
serializer = VideoSerializer(video, many=True)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
@permission_classes([IsAuthenticated])
|
||||||
|
def video_upload(request):
|
||||||
|
parser_classes = (MultiPartParser, FormParser)
|
||||||
|
if request.method == 'POST':
|
||||||
|
serializer = VideoSerializer(data=request.data)
|
||||||
|
if serializer.is_valid():
|
||||||
|
serializer.save()
|
||||||
|
return Response(serializer.data, status=201)
|
||||||
|
return Response({"error": "Invalid data", "details": serializer.errors}, status=400)
|
||||||
|
|
@ -36,6 +36,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),
|
||||||
|
|
||||||
# Users URLs
|
# Users URLs
|
||||||
path('users/', user_views.user_list),
|
path('users/', user_views.user_list),
|
||||||
|
|
|
||||||
515
frontend/package-lock.json
generated
515
frontend/package-lock.json
generated
|
|
@ -16,10 +16,9 @@
|
||||||
"@angular/platform-browser": "^17.2.0",
|
"@angular/platform-browser": "^17.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^17.2.0",
|
"@angular/platform-browser-dynamic": "^17.2.0",
|
||||||
"@angular/router": "^17.2.0",
|
"@angular/router": "^17.2.0",
|
||||||
|
"hls.js": "^1.5.14",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"video.js": "^8.17.2",
|
|
||||||
"videojs-contrib-hls": "^5.15.0",
|
|
||||||
"zone.js": "~0.14.3"
|
"zone.js": "~0.14.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -27,7 +26,6 @@
|
||||||
"@angular/cli": "^17.2.1",
|
"@angular/cli": "^17.2.1",
|
||||||
"@angular/compiler-cli": "^17.2.0",
|
"@angular/compiler-cli": "^17.2.0",
|
||||||
"@types/jasmine": "~5.1.0",
|
"@types/jasmine": "~5.1.0",
|
||||||
"@types/video.js": "^7.3.58",
|
|
||||||
"jasmine-core": "~5.1.0",
|
"jasmine-core": "~5.1.0",
|
||||||
"karma": "~6.4.0",
|
"karma": "~6.4.0",
|
||||||
"karma-chrome-launcher": "~3.2.0",
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
|
@ -2223,6 +2221,7 @@
|
||||||
"version": "7.24.0",
|
"version": "7.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
|
||||||
"integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
|
"integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
},
|
},
|
||||||
|
|
@ -3788,12 +3787,6 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/video.js": {
|
|
||||||
"version": "7.3.58",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/video.js/-/video.js-7.3.58.tgz",
|
|
||||||
"integrity": "sha512-1CQjuSrgbv1/dhmcfQ83eVyYbvGyqhTvb2Opxr0QCV+iJ4J6/J+XWQ3Om59WiwCd1MN3rDUHasx5XRrpUtewYQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.12",
|
"version": "8.5.12",
|
||||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
||||||
|
|
@ -3803,52 +3796,6 @@
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@videojs/http-streaming": {
|
|
||||||
"version": "3.13.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.13.2.tgz",
|
|
||||||
"integrity": "sha512-eCfQp61w00hg7Y9npmLnsJ6UvDF+SsFYzu7mQJgVXxWpVm9AthYWA3KQEKA7F7Sy6yzlm/Sps8BHs5ItelNZgQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@videojs/vhs-utils": "4.0.0",
|
|
||||||
"aes-decrypter": "4.0.1",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"m3u8-parser": "^7.1.0",
|
|
||||||
"mpd-parser": "^1.3.0",
|
|
||||||
"mux.js": "7.0.3",
|
|
||||||
"video.js": "^7 || ^8"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8",
|
|
||||||
"npm": ">=5"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"video.js": "^8.14.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@videojs/vhs-utils": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"url-toolkit": "^2.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8",
|
|
||||||
"npm": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@videojs/xhr": {
|
|
||||||
"version": "2.7.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz",
|
|
||||||
"integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.5.5",
|
|
||||||
"global": "~4.4.0",
|
|
||||||
"is-function": "^1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@vitejs/plugin-basic-ssl": {
|
"node_modules/@vitejs/plugin-basic-ssl": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz",
|
||||||
|
|
@ -4007,14 +3954,6 @@
|
||||||
"@xtuc/long": "4.2.2"
|
"@xtuc/long": "4.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@xmldom/xmldom": {
|
|
||||||
"version": "0.8.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
|
|
||||||
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@xtuc/ieee754": {
|
"node_modules/@xtuc/ieee754": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||||
|
|
@ -4103,31 +4042,6 @@
|
||||||
"node": ">=8.9.0"
|
"node": ">=8.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/aes-decrypter": {
|
|
||||||
"version": "4.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.1.tgz",
|
|
||||||
"integrity": "sha512-H1nh/P9VZXUf17AA5NQfJML88CFjVBDuGkp5zDHa7oEhYN9TTpNLJknRY1ie0iSKWlDf6JRnJKaZVDSQdPy6Cg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@videojs/vhs-utils": "^3.0.5",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"pkcs7": "^1.0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/aes-decrypter/node_modules/@videojs/vhs-utils": {
|
|
||||||
"version": "3.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
|
|
||||||
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"url-toolkit": "^2.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8",
|
|
||||||
"npm": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||||
|
|
@ -4445,20 +4359,6 @@
|
||||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/babel-runtime": {
|
|
||||||
"version": "6.26.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
|
||||||
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
|
||||||
"dependencies": {
|
|
||||||
"core-js": "^2.4.0",
|
|
||||||
"regenerator-runtime": "^0.11.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/babel-runtime/node_modules/regenerator-runtime": {
|
|
||||||
"version": "0.11.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
|
||||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
|
||||||
},
|
|
||||||
"node_modules/balanced-match": {
|
"node_modules/balanced-match": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
|
@ -5229,13 +5129,6 @@
|
||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/core-js": {
|
|
||||||
"version": "2.6.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
|
||||||
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
|
|
||||||
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
|
|
||||||
"hasInstallScript": true
|
|
||||||
},
|
|
||||||
"node_modules/core-js-compat": {
|
"node_modules/core-js-compat": {
|
||||||
"version": "3.37.1",
|
"version": "3.37.1",
|
||||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz",
|
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz",
|
||||||
|
|
@ -5664,11 +5557,6 @@
|
||||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dom-walk": {
|
|
||||||
"version": "0.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
|
||||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
|
||||||
},
|
|
||||||
"node_modules/domelementtype": {
|
"node_modules/domelementtype": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
|
|
@ -5906,14 +5794,6 @@
|
||||||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/es5-shim": {
|
|
||||||
"version": "4.6.7",
|
|
||||||
"resolved": "https://registry.npmjs.org/es5-shim/-/es5-shim-4.6.7.tgz",
|
|
||||||
"integrity": "sha512-jg21/dmlrNQI7JyyA2w7n+yifSxBng0ZralnSfVZjoCawgNTCnS+yBCyVM9DL5itm7SUnDGgv7hcq2XCZX4iRQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.20.1",
|
"version": "0.20.1",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
|
||||||
|
|
@ -6622,15 +6502,6 @@
|
||||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/global": {
|
|
||||||
"version": "4.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
|
|
||||||
"integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
|
|
||||||
"dependencies": {
|
|
||||||
"min-document": "^2.19.0",
|
|
||||||
"process": "^0.11.10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/globals": {
|
"node_modules/globals": {
|
||||||
"version": "11.12.0",
|
"version": "11.12.0",
|
||||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||||
|
|
@ -6740,6 +6611,11 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hls.js": {
|
||||||
|
"version": "1.5.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.5.14.tgz",
|
||||||
|
"integrity": "sha512-5wLiQ2kWJMui6oUslaq8PnPOv1vjuee5gTxjJD0DSsccY12OXtDT0h137UuqjczNeHzeEYR0ROZQibKNMr7Mzg=="
|
||||||
|
},
|
||||||
"node_modules/hosted-git-info": {
|
"node_modules/hosted-git-info": {
|
||||||
"version": "7.0.2",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
|
||||||
|
|
@ -7108,11 +6984,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/individual": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/individual/-/individual-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-pWt8hBCqJsUWI/HtcfWod7+N9SgAqyPEaF7JQjwzjn5vGrpg6aQ5qeAFQ7dx//UH4J1O+7xqew+gCeeFt6xN/g=="
|
|
||||||
},
|
|
||||||
"node_modules/inflight": {
|
"node_modules/inflight": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
|
@ -7271,11 +7142,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-function": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
|
|
||||||
},
|
|
||||||
"node_modules/is-glob": {
|
"node_modules/is-glob": {
|
||||||
"version": "4.0.3",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||||
|
|
@ -8180,30 +8046,6 @@
|
||||||
"yallist": "^3.0.2"
|
"yallist": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/m3u8-parser": {
|
|
||||||
"version": "7.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.1.0.tgz",
|
|
||||||
"integrity": "sha512-7N+pk79EH4oLKPEYdgRXgAsKDyA/VCo0qCHlUwacttQA0WqsjZQYmNfywMvjlY9MpEBVZEt0jKFd73Kv15EBYQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@videojs/vhs-utils": "^3.0.5",
|
|
||||||
"global": "^4.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/m3u8-parser/node_modules/@videojs/vhs-utils": {
|
|
||||||
"version": "3.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-3.0.5.tgz",
|
|
||||||
"integrity": "sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"global": "^4.4.0",
|
|
||||||
"url-toolkit": "^2.2.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8",
|
|
||||||
"npm": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/magic-string": {
|
"node_modules/magic-string": {
|
||||||
"version": "0.30.8",
|
"version": "0.30.8",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
||||||
|
|
@ -8381,14 +8223,6 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/min-document": {
|
|
||||||
"version": "2.19.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
|
|
||||||
"integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"dom-walk": "^0.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mini-css-extract-plugin": {
|
"node_modules/mini-css-extract-plugin": {
|
||||||
"version": "2.8.1",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz",
|
||||||
|
|
@ -8635,20 +8469,6 @@
|
||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mpd-parser": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@videojs/vhs-utils": "^4.0.0",
|
|
||||||
"@xmldom/xmldom": "^0.8.3",
|
|
||||||
"global": "^4.4.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"mpd-to-m3u8-json": "bin/parse.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/mrmime": {
|
"node_modules/mrmime": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||||
|
|
@ -8686,22 +8506,6 @@
|
||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mux.js": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-gzlzJVEGFYPtl2vvEiJneSWAWD4nfYRHD5XgxmB2gWvXraMPOYk+sxfvexmNfjQUFpmk6hwLR5C6iSFmuwCHdQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.11.2",
|
|
||||||
"global": "^4.4.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"muxjs-transmux": "bin/transmux.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8",
|
|
||||||
"npm": ">=5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||||
|
|
@ -9403,11 +9207,6 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parse-headers": {
|
|
||||||
"version": "2.0.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
|
|
||||||
"integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA=="
|
|
||||||
},
|
|
||||||
"node_modules/parse-json": {
|
"node_modules/parse-json": {
|
||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||||
|
|
@ -9595,17 +9394,6 @@
|
||||||
"nice-napi": "^1.0.2"
|
"nice-napi": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pkcs7": {
|
|
||||||
"version": "1.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
|
|
||||||
"integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.5.5"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"pkcs7": "bin/cli.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/pkg-dir": {
|
"node_modules/pkg-dir": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
|
||||||
|
|
@ -9843,14 +9631,6 @@
|
||||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/process": {
|
|
||||||
"version": "0.11.10",
|
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
|
||||||
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/process-nextick-args": {
|
"node_modules/process-nextick-args": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
|
@ -10126,7 +9906,8 @@
|
||||||
"node_modules/regenerator-runtime": {
|
"node_modules/regenerator-runtime": {
|
||||||
"version": "0.14.1",
|
"version": "0.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/regenerator-transform": {
|
"node_modules/regenerator-transform": {
|
||||||
"version": "0.15.2",
|
"version": "0.15.2",
|
||||||
|
|
@ -10391,14 +10172,6 @@
|
||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/rust-result": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/rust-result/-/rust-result-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-6cJzSBU+J/RJCF063onnQf0cDUOHs9uZI1oroSGnHOph+CQTIJ5Pp2hK5kEQq1+7yE/EEWfulSNXAQ2jikPthA==",
|
|
||||||
"dependencies": {
|
|
||||||
"individual": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/rxjs": {
|
"node_modules/rxjs": {
|
||||||
"version": "7.8.1",
|
"version": "7.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
|
@ -10427,14 +10200,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/safe-json-parse": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-4.0.0.tgz",
|
|
||||||
"integrity": "sha512-RjZPPHugjK0TOzFrLZ8inw44s9bKox99/0AZW9o/BEQVrJfhI+fIHMErnPyRa89/yRXUUr93q+tiN6zhoVV4wQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"rust-result": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/safer-buffer": {
|
"node_modules/safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
|
@ -11474,12 +11239,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||||
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ=="
|
||||||
},
|
},
|
||||||
"node_modules/tsml": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/tsml/-/tsml-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-3KmepnH9SUsoOVtg013CRrL7c+AK7ECaquAsJdvu4288EDJuraqBlP4PDXT/rLEJ9YDn4jqLAzRJsnFPx+V6lg==",
|
|
||||||
"deprecated": "no longer maintained"
|
|
||||||
},
|
|
||||||
"node_modules/tuf-js": {
|
"node_modules/tuf-js": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz",
|
||||||
|
|
@ -11706,11 +11465,6 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/url-toolkit": {
|
|
||||||
"version": "2.2.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/url-toolkit/-/url-toolkit-2.2.5.tgz",
|
|
||||||
"integrity": "sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg=="
|
|
||||||
},
|
|
||||||
"node_modules/util-deprecate": {
|
"node_modules/util-deprecate": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
|
@ -11763,216 +11517,6 @@
|
||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/video.js": {
|
|
||||||
"version": "8.17.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-8.17.2.tgz",
|
|
||||||
"integrity": "sha512-oa4BGAr5H965OBcn83qM9xMMtjtSCRh0zMLnyouD9itQJ994FY/NlYo+XSPujk4NpsBGHSUF/+rGy0Wu5Mrzqg==",
|
|
||||||
"dependencies": {
|
|
||||||
"@babel/runtime": "^7.12.5",
|
|
||||||
"@videojs/http-streaming": "3.13.2",
|
|
||||||
"@videojs/vhs-utils": "^4.0.0",
|
|
||||||
"@videojs/xhr": "2.7.0",
|
|
||||||
"aes-decrypter": "^4.0.1",
|
|
||||||
"global": "4.4.0",
|
|
||||||
"m3u8-parser": "^7.1.0",
|
|
||||||
"mpd-parser": "^1.2.2",
|
|
||||||
"mux.js": "^7.0.1",
|
|
||||||
"safe-json-parse": "4.0.0",
|
|
||||||
"videojs-contrib-quality-levels": "4.1.0",
|
|
||||||
"videojs-font": "4.2.0",
|
|
||||||
"videojs-vtt.js": "0.15.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls": {
|
|
||||||
"version": "5.15.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-contrib-hls/-/videojs-contrib-hls-5.15.0.tgz",
|
|
||||||
"integrity": "sha512-18zbMYZ0XRBKTPEayA9bFTWWrqhT9b4G8+zf0czJLD7Epe5PcK1I/3dflTHQeQ5rwlWir+/XnFU3sMg/B2MMcw==",
|
|
||||||
"dependencies": {
|
|
||||||
"aes-decrypter": "1.0.3",
|
|
||||||
"global": "^4.3.0",
|
|
||||||
"m3u8-parser": "2.1.0",
|
|
||||||
"mux.js": "4.3.2",
|
|
||||||
"url-toolkit": "^2.1.3",
|
|
||||||
"video.js": "^5.19.1 || ^6.2.0",
|
|
||||||
"videojs-contrib-media-sources": "4.7.2",
|
|
||||||
"webwackify": "0.1.6"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.10.12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/aes-decrypter": {
|
|
||||||
"version": "1.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-1.0.3.tgz",
|
|
||||||
"integrity": "sha512-rsx8pfx7wJsn+ziYbpJ8XA5c93hKAtBCrfydxJqJCMT+qfjipd/B5wC2xHtBcoxyvlqJcpeAo3K55t0lXOn9yQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"pkcs7": "^0.2.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/global": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-/4AybdwIDU4HkCUbJkZdWpe4P6vuw/CUtu+0I1YlLIPe7OlUO7KNJ+q/rO70CW2/NW6Jc6I62++Hzsf5Alu6rQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"min-document": "^2.19.0",
|
|
||||||
"process": "~0.5.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/m3u8-parser": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-WbEpQ2FUaNGbJ0YanSeyj9D9ruu4FUvz+ZvebIzI2bSME+PUwcPXO1kKXZkjcPUAFruDikoOI5fWQNIA6JCCOQ=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/mux.js": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-g0q6DPdvb3yYcoK7ElBGobdSSrhY/RjPt19U7uUc733aqvc5bCS/aCvL9z+448y+IoCZnYDwyZfQBBXMSmGOaQ=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/pkcs7": {
|
|
||||||
"version": "0.2.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-0.2.3.tgz",
|
|
||||||
"integrity": "sha512-kJRwmADEQUg+qJyRgWLtpEL9q9cFjZschejTEK3GRjKvnsU9G5WWoe/wKqRgbBoqWdVSeTUKP6vIA3Y72M3rWA==",
|
|
||||||
"bin": {
|
|
||||||
"pkcs7": "lib/cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^0.10",
|
|
||||||
"npm": "^1.4.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/process": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-oNpcutj+nYX2FjdEW7PGltWhXulAnFlM0My/k48L90hARCOJtvBbQXc/6itV2jDvU5xAAtonP+r6wmQgCcbAUA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/video.js": {
|
|
||||||
"version": "6.13.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-6.13.0.tgz",
|
|
||||||
"integrity": "sha512-36/JR/GhPQSZj0o+GNbhcEYv/b0SkV9SQsjlodAnzMQYN0TA7VhmqrKPYMCi1NGRYu7S9W3OaFCFoUxkYfSVlg==",
|
|
||||||
"dependencies": {
|
|
||||||
"babel-runtime": "^6.9.2",
|
|
||||||
"global": "4.3.2",
|
|
||||||
"safe-json-parse": "4.0.0",
|
|
||||||
"tsml": "1.0.1",
|
|
||||||
"videojs-font": "2.1.0",
|
|
||||||
"videojs-ie8": "1.1.2",
|
|
||||||
"videojs-vtt.js": "0.12.6",
|
|
||||||
"xhr": "2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/videojs-font": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-zFqWpLrXf1q8NtYx5qtZhMC6SLUFScDmR6j+UGPogobxR21lvXShhnzcNNMdOxJUuFLiToJ/BPpFUQwX4xhpvA=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-hls/node_modules/videojs-vtt.js": {
|
|
||||||
"version": "0.12.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.12.6.tgz",
|
|
||||||
"integrity": "sha512-XFXeGBQiljnElMhwCcZst0RDbZn2n8LU7ZScXryd3a00OaZsHAjdZu/7/RdSr7Z1jHphd45FnOvOQkGK4YrWCQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "^4.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources": {
|
|
||||||
"version": "4.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-contrib-media-sources/-/videojs-contrib-media-sources-4.7.2.tgz",
|
|
||||||
"integrity": "sha512-e6iCHWBFuV05EGo7v+pS9iepObXnJ9joms467gzi8ZjpKVb3ifha9M0Ja24Rd8JfvYpzjltsgDVtGFDvIg4hQQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "^4.3.0",
|
|
||||||
"mux.js": "4.3.2",
|
|
||||||
"video.js": "^5.17.0 || ^6.2.0",
|
|
||||||
"webwackify": "0.1.6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/global": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-/4AybdwIDU4HkCUbJkZdWpe4P6vuw/CUtu+0I1YlLIPe7OlUO7KNJ+q/rO70CW2/NW6Jc6I62++Hzsf5Alu6rQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"min-document": "^2.19.0",
|
|
||||||
"process": "~0.5.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/mux.js": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/mux.js/-/mux.js-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-g0q6DPdvb3yYcoK7ElBGobdSSrhY/RjPt19U7uUc733aqvc5bCS/aCvL9z+448y+IoCZnYDwyZfQBBXMSmGOaQ=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/process": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-oNpcutj+nYX2FjdEW7PGltWhXulAnFlM0My/k48L90hARCOJtvBbQXc/6itV2jDvU5xAAtonP+r6wmQgCcbAUA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/video.js": {
|
|
||||||
"version": "6.13.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/video.js/-/video.js-6.13.0.tgz",
|
|
||||||
"integrity": "sha512-36/JR/GhPQSZj0o+GNbhcEYv/b0SkV9SQsjlodAnzMQYN0TA7VhmqrKPYMCi1NGRYu7S9W3OaFCFoUxkYfSVlg==",
|
|
||||||
"dependencies": {
|
|
||||||
"babel-runtime": "^6.9.2",
|
|
||||||
"global": "4.3.2",
|
|
||||||
"safe-json-parse": "4.0.0",
|
|
||||||
"tsml": "1.0.1",
|
|
||||||
"videojs-font": "2.1.0",
|
|
||||||
"videojs-ie8": "1.1.2",
|
|
||||||
"videojs-vtt.js": "0.12.6",
|
|
||||||
"xhr": "2.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/videojs-font": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-2.1.0.tgz",
|
|
||||||
"integrity": "sha512-zFqWpLrXf1q8NtYx5qtZhMC6SLUFScDmR6j+UGPogobxR21lvXShhnzcNNMdOxJUuFLiToJ/BPpFUQwX4xhpvA=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-media-sources/node_modules/videojs-vtt.js": {
|
|
||||||
"version": "0.12.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.12.6.tgz",
|
|
||||||
"integrity": "sha512-XFXeGBQiljnElMhwCcZst0RDbZn2n8LU7ZScXryd3a00OaZsHAjdZu/7/RdSr7Z1jHphd45FnOvOQkGK4YrWCQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "^4.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-contrib-quality-levels": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "^4.4.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=16",
|
|
||||||
"npm": ">=8"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"video.js": "^8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-font": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ=="
|
|
||||||
},
|
|
||||||
"node_modules/videojs-ie8": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-ie8/-/videojs-ie8-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-0Zb2T4MLkpfZbeGMK/Z93b8Lrepr+rLFoHgQV1CoDeFqXvH7b+Vsd/VHoILGxQrgCSHFQ7mAODR6oyMjuiD4/g==",
|
|
||||||
"dependencies": {
|
|
||||||
"es5-shim": "^4.5.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/videojs-vtt.js": {
|
|
||||||
"version": "0.15.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
|
|
||||||
"integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "^4.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.1.7",
|
"version": "5.1.7",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz",
|
||||||
|
|
@ -12753,11 +12297,6 @@
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webwackify": {
|
|
||||||
"version": "0.1.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/webwackify/-/webwackify-0.1.6.tgz",
|
|
||||||
"integrity": "sha512-pGcw1T3HpNnM/UTRQqqRkkkzythSLts05mB+7Gr00B+0VbL0m39dFL5g20rSIEUt9Wrpw+/8k+snxRlUFHhcqA=="
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||||
|
|
@ -12901,42 +12440,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/xhr": {
|
|
||||||
"version": "2.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/xhr/-/xhr-2.4.0.tgz",
|
|
||||||
"integrity": "sha512-TUbBsdAuJbX8olk9hsDwGK8P1ri1XlV+PdEWkYw+HQQbpkiBR8PLgD1F3kQDPBs9l4Px34hP9rCYAZOCCAENbw==",
|
|
||||||
"dependencies": {
|
|
||||||
"global": "~4.3.0",
|
|
||||||
"is-function": "^1.0.1",
|
|
||||||
"parse-headers": "^2.0.0",
|
|
||||||
"xtend": "^4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xhr/node_modules/global": {
|
|
||||||
"version": "4.3.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz",
|
|
||||||
"integrity": "sha512-/4AybdwIDU4HkCUbJkZdWpe4P6vuw/CUtu+0I1YlLIPe7OlUO7KNJ+q/rO70CW2/NW6Jc6I62++Hzsf5Alu6rQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"min-document": "^2.19.0",
|
|
||||||
"process": "~0.5.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xhr/node_modules/process": {
|
|
||||||
"version": "0.5.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz",
|
|
||||||
"integrity": "sha512-oNpcutj+nYX2FjdEW7PGltWhXulAnFlM0My/k48L90hARCOJtvBbQXc/6itV2jDvU5xAAtonP+r6wmQgCcbAUA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/xtend": {
|
|
||||||
"version": "4.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
|
||||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,9 @@
|
||||||
"@angular/platform-browser": "^17.2.0",
|
"@angular/platform-browser": "^17.2.0",
|
||||||
"@angular/platform-browser-dynamic": "^17.2.0",
|
"@angular/platform-browser-dynamic": "^17.2.0",
|
||||||
"@angular/router": "^17.2.0",
|
"@angular/router": "^17.2.0",
|
||||||
|
"hls.js": "^1.5.14",
|
||||||
"rxjs": "~7.8.0",
|
"rxjs": "~7.8.0",
|
||||||
"tslib": "^2.3.0",
|
"tslib": "^2.3.0",
|
||||||
"video.js": "^8.17.2",
|
|
||||||
"videojs-contrib-hls": "^5.15.0",
|
|
||||||
"zone.js": "~0.14.3"
|
"zone.js": "~0.14.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
@ -29,7 +28,6 @@
|
||||||
"@angular/cli": "^17.2.1",
|
"@angular/cli": "^17.2.1",
|
||||||
"@angular/compiler-cli": "^17.2.0",
|
"@angular/compiler-cli": "^17.2.0",
|
||||||
"@types/jasmine": "~5.1.0",
|
"@types/jasmine": "~5.1.0",
|
||||||
"@types/video.js": "^7.3.58",
|
|
||||||
"jasmine-core": "~5.1.0",
|
"jasmine-core": "~5.1.0",
|
||||||
"karma": "~6.4.0",
|
"karma": "~6.4.0",
|
||||||
"karma-chrome-launcher": "~3.2.0",
|
"karma-chrome-launcher": "~3.2.0",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<section>
|
<section>
|
||||||
@if (currentMovie.length < 0) {
|
@if (currentMovie[0]) {
|
||||||
<!-- If at least one film has been uploaded -->
|
<!-- If at least one film has been uploaded -->
|
||||||
@if (playMovie === "") {
|
@if (playMovie === "") {
|
||||||
<app-header [browse]="true"></app-header>
|
<app-header [browse]="true"></app-header>
|
||||||
|
|
@ -18,6 +18,38 @@
|
||||||
<div class="back-button" (click)="closeVideo()">
|
<div class="back-button" (click)="closeVideo()">
|
||||||
<img src="./../../../../assets/img/back.svg" alt="Back" />
|
<img src="./../../../../assets/img/back.svg" alt="Back" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="resolution-controls">
|
||||||
|
<button
|
||||||
|
[ngClass]="{
|
||||||
|
'resolution-btn': true,
|
||||||
|
active: currentResolution === '480p'
|
||||||
|
}"
|
||||||
|
[disabled]="currentResolution === '480p'"
|
||||||
|
(click)="changeResolution('480p')"
|
||||||
|
>
|
||||||
|
480p
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
[ngClass]="{
|
||||||
|
'resolution-btn': true,
|
||||||
|
active: currentResolution === '720p'
|
||||||
|
}"
|
||||||
|
[disabled]="currentResolution === '720p'"
|
||||||
|
(click)="changeResolution('720p')"
|
||||||
|
>
|
||||||
|
720p
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
[ngClass]="{
|
||||||
|
'resolution-btn': true,
|
||||||
|
active: currentResolution === '1080p'
|
||||||
|
}"
|
||||||
|
[disabled]="currentResolution === '1080p'"
|
||||||
|
(click)="changeResolution('1080p')"
|
||||||
|
>
|
||||||
|
1080p
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div class="logo">
|
<div class="logo">
|
||||||
<img src="./../../../../assets/img/logo_ci.svg" alt="Logo" />
|
<img src="./../../../../assets/img/logo_ci.svg" alt="Logo" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -84,3 +84,41 @@ section {
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolution Buttons
|
||||||
|
|
||||||
|
.resolution-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
margin: 18px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resolution-btn {
|
||||||
|
background-color: $light-blue;
|
||||||
|
color: $white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resolution-btn.active {
|
||||||
|
background-color: $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resolution-btn:disabled {
|
||||||
|
cursor: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resolution-btn:not(.active):hover {
|
||||||
|
background-color: $blue;
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.resolution-btn:focus {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 3px rgba(38, 143, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,17 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
import { HeaderComponent } from '../../../shared/components/header/header.component';
|
import { HeaderComponent } from '../../../shared/components/header/header.component';
|
||||||
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
||||||
import { CategoriesComponent } from './categories/categories.component';
|
import { CategoriesComponent } from './categories/categories.component';
|
||||||
import { AuthService } from '../../../services/auth.service';
|
import { AuthService } from '../../../services/auth.service';
|
||||||
import { MovieService } from '../../../services/movie.service';
|
import { MovieService } from '../../../services/movie.service';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { VideoPlayerComponent } from './vjs-player/vjs-player.component';
|
import { VideoPlayerComponent } from './video-player/video-player.component';
|
||||||
import { BtnSmallComponent } from '../../../shared/components/buttons/btn-small/btn-small.component';
|
import { BtnSmallComponent } from '../../../shared/components/buttons/btn-small/btn-small.component';
|
||||||
import { UploadMovieComponent } from './upload-movie/upload-movie.component';
|
import { UploadMovieComponent } from './upload-movie/upload-movie.component';
|
||||||
|
|
||||||
|
|
@ -25,10 +31,12 @@ import { UploadMovieComponent } from './upload-movie/upload-movie.component';
|
||||||
styleUrl: './browse.component.scss',
|
styleUrl: './browse.component.scss',
|
||||||
})
|
})
|
||||||
export class BrowseComponent implements OnInit {
|
export class BrowseComponent implements OnInit {
|
||||||
|
@ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent;
|
||||||
movies: any[] = [];
|
movies: any[] = [];
|
||||||
currentMovie: any[] = [];
|
currentMovie: any[] = [];
|
||||||
playMovie: string = '';
|
playMovie: string = '';
|
||||||
uploadMovieOverview: boolean = false;
|
uploadMovieOverview: boolean = false;
|
||||||
|
currentResolution: '480p' | '720p' | '1080p' = '720p';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
|
|
@ -40,6 +48,13 @@ export class BrowseComponent implements OnInit {
|
||||||
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
|
this.currentMovie.length === 0 ? this.loadRandomMovie() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changeResolution(resolution: '480p' | '720p' | '1080p') {
|
||||||
|
if (this.videoPlayer) {
|
||||||
|
this.videoPlayer.switchResolution(resolution);
|
||||||
|
this.currentResolution = resolution;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async loadAllMovies() {
|
async loadAllMovies() {
|
||||||
this.movies = await this.movieService.getAllMovies();
|
this.movies = await this.movieService.getAllMovies();
|
||||||
}
|
}
|
||||||
|
|
@ -66,8 +81,6 @@ export class BrowseComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleUploadMovieOverview(value: any) {
|
toggleUploadMovieOverview(value: any) {
|
||||||
console.log(value);
|
|
||||||
|
|
||||||
this.uploadMovieOverview = value;
|
this.uploadMovieOverview = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,7 @@
|
||||||
'/media/videos/' +
|
'/media/videos/' +
|
||||||
currentMovie[0]?.id +
|
currentMovie[0]?.id +
|
||||||
'/' +
|
'/' +
|
||||||
currentMovie[0]?.file_name +
|
currentMovie[0]?.file_name
|
||||||
'_1080p.m3u8'
|
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
></app-btn-large>
|
></app-btn-large>
|
||||||
|
|
|
||||||
|
|
@ -73,20 +73,19 @@
|
||||||
type="file"
|
type="file"
|
||||||
id="videoFile"
|
id="videoFile"
|
||||||
name="videoFile"
|
name="videoFile"
|
||||||
#videoFile="ngModel"
|
|
||||||
placeholder="Video file"
|
placeholder="Video file"
|
||||||
[(ngModel)]="movieData.videoFile"
|
(change)="onFileChange($event)"
|
||||||
[class.error-border]="!videoFile.valid && videoFile.touched"
|
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
<div class="error-msg">
|
<div class="error-msg"></div>
|
||||||
@if (!videoFile.valid && videoFile.touched) {
|
|
||||||
<p>Please enter the movie file</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<app-btn-large
|
<app-btn-large
|
||||||
[value]="'Get Started'"
|
[value]="'Upload Movie'"
|
||||||
[disabled]="!movieData.title"
|
[disabled]="
|
||||||
|
!movieData.title ||
|
||||||
|
!movieData.description ||
|
||||||
|
!movieData.filmGenre ||
|
||||||
|
!movieData.videoFile
|
||||||
|
"
|
||||||
></app-btn-large>
|
></app-btn-large>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { Component, EventEmitter, Output } from '@angular/core';
|
||||||
import { FormsModule, NgForm } from '@angular/forms';
|
import { FormsModule, NgForm } from '@angular/forms';
|
||||||
import { ErrorService } from '../../../../services/error.service';
|
import { ErrorService } from '../../../../services/error.service';
|
||||||
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
|
import { BtnLargeComponent } from '../../../../shared/components/buttons/btn-large/btn-large.component';
|
||||||
|
import { MovieService } from '../../../../services/movie.service';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-upload-movie',
|
selector: 'app-upload-movie',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -17,10 +18,13 @@ export class UploadMovieComponent {
|
||||||
title: '',
|
title: '',
|
||||||
description: '',
|
description: '',
|
||||||
filmGenre: '',
|
filmGenre: '',
|
||||||
videoFile: '',
|
videoFile: null as File | null,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(public errorService: ErrorService) {}
|
constructor(
|
||||||
|
public errorService: ErrorService,
|
||||||
|
private movieService: MovieService
|
||||||
|
) {}
|
||||||
|
|
||||||
stopPropagation(event: MouseEvent) {
|
stopPropagation(event: MouseEvent) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
@ -30,9 +34,30 @@ export class UploadMovieComponent {
|
||||||
this.toggleUploadMovieOverview.emit(false);
|
this.toggleUploadMovieOverview.emit(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onFileChange(event: any) {
|
||||||
|
const file = event.target.files[0];
|
||||||
|
if (file) {
|
||||||
|
this.movieData.videoFile = file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async onSubmit(ngForm: NgForm) {
|
async onSubmit(ngForm: NgForm) {
|
||||||
if (ngForm.submitted && ngForm.form.valid) {
|
if (ngForm.submitted && ngForm.form.valid) {
|
||||||
console.log('send');
|
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);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await this.movieService.uploadMovie(formData);
|
||||||
|
ngForm.resetForm();
|
||||||
|
this.uploadMovieOverview();
|
||||||
|
this.errorService.clearError();
|
||||||
|
} catch (error) {
|
||||||
|
this.errorService.handleError(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
<video controls></video>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { VideoPlayerComponent } from './vjs-player.component';
|
import { VideoPlayerComponent } from './video-player.component';
|
||||||
|
|
||||||
describe('VjsPlayerComponent', () => {
|
describe('VideoPlayerComponent', () => {
|
||||||
let component: VideoPlayerComponent;
|
let component: VideoPlayerComponent;
|
||||||
let fixture: ComponentFixture<VideoPlayerComponent>;
|
let fixture: ComponentFixture<VideoPlayerComponent>;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
import { Component, OnInit, OnDestroy, ElementRef, Input } from '@angular/core';
|
||||||
|
import Hls from 'hls.js';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-video-player',
|
||||||
|
standalone: true,
|
||||||
|
templateUrl: './video-player.component.html',
|
||||||
|
styleUrls: ['./video-player.component.scss'],
|
||||||
|
})
|
||||||
|
export class VideoPlayerComponent implements OnInit, OnDestroy {
|
||||||
|
@Input() playMovie: string = '';
|
||||||
|
private hls: Hls | null = null;
|
||||||
|
private videoElement: HTMLVideoElement | null = null;
|
||||||
|
private resolutionUrls: { [key: string]: string } = {};
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.videoElement = this.elementRef.nativeElement.querySelector(
|
||||||
|
'video'
|
||||||
|
) as HTMLVideoElement;
|
||||||
|
|
||||||
|
if (this.playMovie) {
|
||||||
|
this.resolutionUrls = {
|
||||||
|
'480p': `${this.playMovie}_480p.m3u8`,
|
||||||
|
'720p': `${this.playMovie}_720p.m3u8`,
|
||||||
|
'1080p': `${this.playMovie}_1080p.m3u8`,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Hls.isSupported() && this.videoElement) {
|
||||||
|
this.hls = new Hls();
|
||||||
|
this.hls.loadSource(this.resolutionUrls['720p']); // Default resolution
|
||||||
|
this.hls.attachMedia(this.videoElement);
|
||||||
|
this.hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
|
this.videoElement?.play();
|
||||||
|
});
|
||||||
|
} else if (
|
||||||
|
this.videoElement.canPlayType('application/vnd.apple.mpegurl')
|
||||||
|
) {
|
||||||
|
this.videoElement.src = this.resolutionUrls['720p']; // Default resolution
|
||||||
|
this.videoElement.addEventListener('canplay', () => {
|
||||||
|
this.videoElement?.play();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateScreenDimensions();
|
||||||
|
} else {
|
||||||
|
console.error('playMovie is not set.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateScreenDimensions() {
|
||||||
|
if (this.videoElement) {
|
||||||
|
this.videoElement.style.width = `${window.innerWidth}px`;
|
||||||
|
this.videoElement.style.height = `${window.innerHeight}px`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.hls) {
|
||||||
|
this.hls.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to switch resolution
|
||||||
|
public switchResolution(resolution: '480p' | '720p' | '1080p') {
|
||||||
|
if (this.resolutionUrls[resolution]) {
|
||||||
|
if (this.hls) {
|
||||||
|
this.hls.loadSource(this.resolutionUrls[resolution]);
|
||||||
|
this.hls.attachMedia(this.videoElement!);
|
||||||
|
} else if (this.videoElement) {
|
||||||
|
this.videoElement.src = this.resolutionUrls[resolution];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error(`Resolution URL for ${resolution} not found.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<video id="my-video" class="video-js vjs-default-skin">
|
|
||||||
<source src="{{ playMovie }}" type="application/x-mpegURL" />
|
|
||||||
</video>
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
import {
|
|
||||||
Component,
|
|
||||||
OnInit,
|
|
||||||
OnDestroy,
|
|
||||||
ElementRef,
|
|
||||||
Input,
|
|
||||||
HostListener,
|
|
||||||
} from '@angular/core';
|
|
||||||
import videojs from 'video.js';
|
|
||||||
import log from 'video.js/dist/types/utils/log';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-video-player',
|
|
||||||
standalone: true,
|
|
||||||
templateUrl: './vjs-player.component.html',
|
|
||||||
styleUrls: ['./vjs-player.component.scss'],
|
|
||||||
})
|
|
||||||
export class VideoPlayerComponent implements OnInit, OnDestroy {
|
|
||||||
@Input() playMovie: string = '';
|
|
||||||
private player: any;
|
|
||||||
private screenWidth: number = 0;
|
|
||||||
private screenHeight: number = 0;
|
|
||||||
|
|
||||||
constructor(private elementRef: ElementRef) {}
|
|
||||||
|
|
||||||
ngOnInit(): void {
|
|
||||||
this.updateScreenDimensions();
|
|
||||||
this.player = videojs(
|
|
||||||
this.elementRef.nativeElement.querySelector('video'),
|
|
||||||
{
|
|
||||||
controls: true,
|
|
||||||
autoplay: true,
|
|
||||||
height: this.screenHeight,
|
|
||||||
width: this.screenWidth,
|
|
||||||
preload: 'auto',
|
|
||||||
sources: [
|
|
||||||
{
|
|
||||||
src: this.playMovie,
|
|
||||||
type: 'application/x-mpegURL',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateScreenDimensions() {
|
|
||||||
this.screenWidth = window.innerWidth;
|
|
||||||
this.screenHeight = window.innerHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
if (this.player) {
|
|
||||||
this.player.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -21,6 +21,15 @@ export class MovieService {
|
||||||
return lastValueFrom(this.http.get(url, { headers }));
|
return lastValueFrom(this.http.get(url, { headers }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async uploadMovie(formData: FormData) {
|
||||||
|
const headers = this.getAuthHeaders();
|
||||||
|
await lastValueFrom(
|
||||||
|
this.http.post(`${environment.baseUrl}/content/upload/`, formData, {
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private getAuthHeaders(): HttpHeaders {
|
private getAuthHeaders(): HttpHeaders {
|
||||||
let authToken = localStorage.getItem('authToken');
|
let authToken = localStorage.getItem('authToken');
|
||||||
if (!authToken) {
|
if (!authToken) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue