videos werden in .m3u8 beim hochladen gerendert, videojs player hinzugefügt
This commit is contained in:
parent
ced191e0fa
commit
8fa95443aa
14 changed files with 720 additions and 88 deletions
|
|
@ -8,7 +8,7 @@ class Video(models.Model):
|
|||
description = models.CharField(max_length=500)
|
||||
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)
|
||||
thumbnail = models.ImageField(upload_to='thumbnails/', blank=True, null=True)
|
||||
file_name = models.CharField(max_length=50, blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
return f'({self.id}) {self.title}'
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
from .models import Video
|
||||
from content.tasks import convert_video, create_thumbnails
|
||||
from .tasks import convert_video_to_hls, create_thumbnails, delete_original_video
|
||||
from django.dispatch import receiver
|
||||
from django.db.models.signals import post_save, post_delete
|
||||
from django.conf import settings
|
||||
import os
|
||||
import django_rq
|
||||
import shutil
|
||||
|
||||
@receiver(post_save, sender=Video)
|
||||
def video_post_save(sender, instance, created, **kwargs):
|
||||
|
|
@ -14,41 +15,36 @@ def video_post_save(sender, instance, created, **kwargs):
|
|||
if created:
|
||||
queue = django_rq.get_queue("default", autocommit=True)
|
||||
|
||||
#Convert Video
|
||||
queue.enqueue(convert_video, instance.video_file.path, "480")
|
||||
queue.enqueue(convert_video, instance.video_file.path, "720")
|
||||
queue.enqueue(convert_video, instance.video_file.path, "1080")
|
||||
#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, "720", instance.id)
|
||||
queue.enqueue(convert_video_to_hls, instance.video_file.path, "1080", instance.id)
|
||||
|
||||
#Create Thumbnail
|
||||
queue.enqueue(create_thumbnails, instance)
|
||||
#Create thumbnail
|
||||
queue.enqueue(create_thumbnails, instance, instance.id)
|
||||
|
||||
# Delete the original video file
|
||||
queue.enqueue(delete_original_video, instance.video_file.path)
|
||||
|
||||
@receiver(post_delete, sender=Video)
|
||||
def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||
"""
|
||||
Deletes video file and its converted files from filesystem
|
||||
when corresponding `Video` object is deleted.
|
||||
Deletes the video and all converted files from the file system,
|
||||
when the corresponding `Video` object is deleted.
|
||||
"""
|
||||
# Delete the original video file
|
||||
if instance.video_file:
|
||||
if os.path.isfile(instance.video_file.path):
|
||||
os.remove(instance.video_file.path)
|
||||
|
||||
# Delete the converted videos
|
||||
if instance.video_file:
|
||||
delete_converted_files(instance.video_file.path)
|
||||
|
||||
# Delete the thumbnails
|
||||
if instance.thumbnail:
|
||||
thumbnail_dir = settings.THUMBNAIL_DIR
|
||||
base_filename = os.path.splitext(os.path.basename(instance.video_file.path))[0]
|
||||
thumbnail_1080p_path = os.path.join(thumbnail_dir, base_filename + '_1080p.jpg')
|
||||
thumbnail_480_path = os.path.join(thumbnail_dir, base_filename + '_480p.jpg')
|
||||
|
||||
if os.path.isfile(thumbnail_1080p_path):
|
||||
os.remove(thumbnail_1080p_path)
|
||||
if os.path.isfile(thumbnail_480_path):
|
||||
os.remove(thumbnail_480_path)
|
||||
main_directory = os.path.dirname(instance.video_file.path)
|
||||
model_directory = os.path.join(main_directory, str(instance.id))
|
||||
delete_directory(model_directory)
|
||||
|
||||
def delete_directory(directory_path):
|
||||
"""
|
||||
Deletes the specified directory recursively.
|
||||
"""
|
||||
if os.path.exists(directory_path):
|
||||
shutil.rmtree(directory_path)
|
||||
else:
|
||||
print(f"Folder not found: {directory_path}")
|
||||
|
||||
def remove_first_mp4(filename):
|
||||
"""
|
||||
Remove the first .mp4 extension from the filename.
|
||||
|
|
|
|||
|
|
@ -1,31 +1,70 @@
|
|||
import re
|
||||
import subprocess
|
||||
import ffmpeg
|
||||
import os
|
||||
from django.conf import settings
|
||||
from .models import Video
|
||||
|
||||
def convert_video(source, resolution):
|
||||
target = source + f'_{resolution}p.mp4'
|
||||
target = remove_first_mp4(target)
|
||||
ffmpeg_path = '/opt/homebrew/bin/ffmpeg'
|
||||
cmd = [ffmpeg_path, '-i', source, '-s', f'hd{resolution}', '-c:v', 'libx264', '-crf', '23', '-c:a', 'aac', '-strict', '-2', target]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True)
|
||||
def convert_video_to_hls(source, resolution, model_id):
|
||||
target_dir = os.path.join(os.path.dirname(source), str(model_id))
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
base_filename = os.path.basename(source).split(".")[0]
|
||||
target = os.path.join(target_dir, f'{base_filename}_{resolution}p')
|
||||
|
||||
def remove_first_mp4(filename):
|
||||
name_part, ext_part = filename.split('.mp4', 1)
|
||||
new_filename = name_part + ext_part
|
||||
return new_filename
|
||||
|
||||
def create_thumbnails(self):
|
||||
video_file_path = self.video_file.path
|
||||
thumbnail_dir = settings.THUMBNAIL_DIR
|
||||
ffmpeg_path = '/opt/homebrew/bin/ffmpeg'
|
||||
cmd = [
|
||||
ffmpeg_path,
|
||||
'-i', source,
|
||||
'-s', f'hd{resolution}',
|
||||
'-c:v', 'libx264',
|
||||
'-crf', '23',
|
||||
'-c:a', 'aac',
|
||||
'-strict', '-2',
|
||||
'-hls_time', '10',
|
||||
'-hls_playlist_type', 'vod',
|
||||
'-hls_segment_filename', os.path.join(target_dir, f'{base_filename}_{resolution}p_%03d.ts'),
|
||||
f'{target}.m3u8'
|
||||
]
|
||||
|
||||
result = 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):
|
||||
"""
|
||||
Deletes the original MP4 file.
|
||||
"""
|
||||
try:
|
||||
os.remove(source)
|
||||
except OSError as e:
|
||||
print(f"Error deleting original file: {e}")
|
||||
|
||||
def create_thumbnails(self, model_id):
|
||||
video_file_path = self.video_file.path
|
||||
thumbnail_dir = os.path.join(settings.THUMBNAIL_DIR, str(model_id))
|
||||
|
||||
base_filename = os.path.splitext(os.path.basename(video_file_path))[0]
|
||||
thumbnail_1080p_filename = base_filename + '_1080p.jpg'
|
||||
thumbnail_1080p_path = os.path.join(thumbnail_dir, thumbnail_1080p_filename)
|
||||
thumbnail_480_filename = base_filename + '_480p.jpg'
|
||||
thumbnail_480_path = os.path.join(thumbnail_dir, thumbnail_480_filename)
|
||||
thumbnail_path = os.path.join(thumbnail_dir, base_filename + ".jpg")
|
||||
|
||||
|
||||
if not os.path.exists(thumbnail_dir):
|
||||
os.makedirs(thumbnail_dir)
|
||||
|
||||
|
|
@ -33,9 +72,5 @@ def create_thumbnails(self):
|
|||
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)
|
||||
|
||||
# Hier speichern wir nur das Thumbnail für die Vorschau im Modell
|
||||
self.thumbnail = os.path.relpath(thumbnail_path, start=settings.MEDIA_ROOT)
|
||||
self.save()
|
||||
|
||||
except ffmpeg._run.Error as e:
|
||||
print(f"Ein Fehler ist aufgetreten: {e.stderr.decode()}")
|
||||
|
|
@ -20,18 +20,11 @@
|
|||
"outputPath": "dist/frontend",
|
||||
"index": "src/index.html",
|
||||
"browser": "src/main.ts",
|
||||
"polyfills": [
|
||||
"zone.js"
|
||||
],
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
],
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
|
|
@ -79,20 +72,18 @@
|
|||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"polyfills": [
|
||||
"zone.js",
|
||||
"zone.js/testing"
|
||||
],
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets"
|
||||
],
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": [
|
||||
"src/styles.scss"
|
||||
"src/styles.scss",
|
||||
"node_modules/video.js/dist/video-js.css"
|
||||
],
|
||||
"scripts": []
|
||||
"scripts": [
|
||||
"node_modules/video.js/dist/video.min.js",
|
||||
"node_modules/videojs-contrib-hls/dist/videojs-contrib-hls.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
509
frontend/package-lock.json
generated
509
frontend/package-lock.json
generated
|
|
@ -18,6 +18,8 @@
|
|||
"@angular/router": "^17.2.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"video.js": "^8.17.2",
|
||||
"videojs-contrib-hls": "^5.15.0",
|
||||
"zone.js": "~0.14.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -25,6 +27,7 @@
|
|||
"@angular/cli": "^17.2.1",
|
||||
"@angular/compiler-cli": "^17.2.0",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"@types/video.js": "^7.3.58",
|
||||
"jasmine-core": "~5.1.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
|
|
@ -2220,7 +2223,6 @@
|
|||
"version": "7.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.0.tgz",
|
||||
"integrity": "sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.14.0"
|
||||
},
|
||||
|
|
@ -3786,6 +3788,12 @@
|
|||
"@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": {
|
||||
"version": "8.5.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
|
||||
|
|
@ -3795,6 +3803,52 @@
|
|||
"@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": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.1.0.tgz",
|
||||
|
|
@ -3953,6 +4007,14 @@
|
|||
"@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": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
|
|
@ -4041,6 +4103,31 @@
|
|||
"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": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
|
||||
|
|
@ -4358,6 +4445,20 @@
|
|||
"@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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
|
|
@ -5128,6 +5229,13 @@
|
|||
"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": {
|
||||
"version": "3.37.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz",
|
||||
|
|
@ -5556,6 +5664,11 @@
|
|||
"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": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
|
|
@ -5793,6 +5906,14 @@
|
|||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||
"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": {
|
||||
"version": "0.20.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.1.tgz",
|
||||
|
|
@ -6501,6 +6622,15 @@
|
|||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||
"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": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
|
|
@ -6978,6 +7108,11 @@
|
|||
"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": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
|
|
@ -7136,6 +7271,11 @@
|
|||
"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": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
|
|
@ -8040,6 +8180,30 @@
|
|||
"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": {
|
||||
"version": "0.30.8",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz",
|
||||
|
|
@ -8217,6 +8381,14 @@
|
|||
"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": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.8.1.tgz",
|
||||
|
|
@ -8463,6 +8635,20 @@
|
|||
"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": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||
|
|
@ -8500,6 +8686,22 @@
|
|||
"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": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
|
|
@ -9201,6 +9403,11 @@
|
|||
"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": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
|
||||
|
|
@ -9388,6 +9595,17 @@
|
|||
"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": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
|
||||
|
|
@ -9625,6 +9843,14 @@
|
|||
"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": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
|
@ -9900,8 +10126,7 @@
|
|||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.14.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
|
||||
},
|
||||
"node_modules/regenerator-transform": {
|
||||
"version": "0.15.2",
|
||||
|
|
@ -10166,6 +10391,14 @@
|
|||
"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": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
|
|
@ -10194,6 +10427,14 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"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": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
|
|
@ -11233,6 +11474,12 @@
|
|||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
|
||||
"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": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-2.2.1.tgz",
|
||||
|
|
@ -11459,6 +11706,11 @@
|
|||
"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": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
@ -11511,6 +11763,216 @@
|
|||
"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": {
|
||||
"version": "5.1.7",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.1.7.tgz",
|
||||
|
|
@ -12291,6 +12753,11 @@
|
|||
"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": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
|
|
@ -12434,6 +12901,42 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
"@angular/router": "^17.2.0",
|
||||
"rxjs": "~7.8.0",
|
||||
"tslib": "^2.3.0",
|
||||
"video.js": "^8.17.2",
|
||||
"videojs-contrib-hls": "^5.15.0",
|
||||
"zone.js": "~0.14.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -27,6 +29,7 @@
|
|||
"@angular/cli": "^17.2.1",
|
||||
"@angular/compiler-cli": "^17.2.0",
|
||||
"@types/jasmine": "~5.1.0",
|
||||
"@types/video.js": "^7.3.58",
|
||||
"jasmine-core": "~5.1.0",
|
||||
"karma": "~6.4.0",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
|
|
|
|||
|
|
@ -20,13 +20,11 @@
|
|||
<img src="./../../../../assets/img/logo_ci.svg" alt="Logo" />
|
||||
</div>
|
||||
</div>
|
||||
<video width="100%" height="100%" controls autoplay>
|
||||
<source
|
||||
src="{{ playMovie.replace('.mp4', '_1080p.mp4') }}"
|
||||
type="video/mp4"
|
||||
/>
|
||||
<app-video-player [playMovie]="playMovie"></app-video-player>
|
||||
<!-- <video width="100%" height="100%" controls autoplay>
|
||||
<source src="{{ playMovie }}" type="video/mp4" />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
</video> -->
|
||||
</div>
|
||||
}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { HeaderComponent } from '../../../shared/components/header/header.component';
|
||||
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
||||
import { CategoriesComponent } from './categories/categories.component';
|
||||
|
|
@ -6,6 +6,7 @@ import { AuthService } from '../../../services/auth.service';
|
|||
import { MovieService } from '../../../services/movie.service';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { VideoPlayerComponent } from './vjs-player/vjs-player.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-browse',
|
||||
|
|
@ -15,6 +16,7 @@ import { CommonModule } from '@angular/common';
|
|||
HeaderComponent,
|
||||
HeroBannerComponent,
|
||||
CategoriesComponent,
|
||||
VideoPlayerComponent,
|
||||
],
|
||||
templateUrl: './browse.component.html',
|
||||
styleUrl: './browse.component.scss',
|
||||
|
|
|
|||
|
|
@ -8,8 +8,13 @@
|
|||
<img
|
||||
[ngClass]="{ selected: movie.id === currentMovie }"
|
||||
src="{{
|
||||
environmentBaseUrl + movie.thumbnail.replace('.jpg', '_480p.jpg')
|
||||
}} }}"
|
||||
environmentBaseUrl +
|
||||
'/media/thumbnails/' +
|
||||
movie.id +
|
||||
'/' +
|
||||
movie.file_name +
|
||||
'_480p.jpg'
|
||||
}}"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -28,7 +33,12 @@
|
|||
<img
|
||||
[ngClass]="{ selected: movie.id === currentMovie }"
|
||||
src="{{
|
||||
environmentBaseUrl + movie.thumbnail.replace('.jpg', '_480p.jpg')
|
||||
environmentBaseUrl +
|
||||
'/media/thumbnails/' +
|
||||
movie.id +
|
||||
'/' +
|
||||
movie.file_name +
|
||||
'_480p.jpg'
|
||||
}}"
|
||||
alt=""
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,21 +4,34 @@
|
|||
'background-image':
|
||||
'url(' +
|
||||
environmentBaseUrl +
|
||||
currentMovie[0]?.thumbnail.replace('.jpg', '_1080p.jpg') +
|
||||
'/media/thumbnails/' +
|
||||
currentMovie[0]?.id +
|
||||
'/' +
|
||||
currentMovie[0]?.file_name +
|
||||
'_1080p.jpg' +
|
||||
')'
|
||||
}"
|
||||
>
|
||||
@if (currentMovie.length > 0) {
|
||||
<div class="content">
|
||||
<div class="title">{{ currentMovie[0]?.title }}</div>
|
||||
<div class="title">{{ currentMovie[0].title }}</div>
|
||||
<div class="description">
|
||||
{{ currentMovie[0]?.description }}
|
||||
{{ currentMovie[0].description }}
|
||||
</div>
|
||||
<app-btn-large
|
||||
[value]="'Play'"
|
||||
[imgPath]="'play'"
|
||||
[imgReverse]="true"
|
||||
(click)="playMovieId(environmentBaseUrl + currentMovie[0]?.video_file)"
|
||||
(click)="
|
||||
playMovieId(
|
||||
environmentBaseUrl +
|
||||
'/media/videos/' +
|
||||
currentMovie[0]?.id +
|
||||
'/' +
|
||||
currentMovie[0]?.file_name +
|
||||
'_1080p.m3u8'
|
||||
)
|
||||
"
|
||||
></app-btn-large>
|
||||
</div>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<video id="my-video" class="video-js vjs-default-skin">
|
||||
<source src="{{ playMovie }}" type="application/x-mpegURL" />
|
||||
</video>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { VideoPlayerComponent } from './vjs-player.component';
|
||||
|
||||
describe('VjsPlayerComponent', () => {
|
||||
let component: VideoPlayerComponent;
|
||||
let fixture: ComponentFixture<VideoPlayerComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [VideoPlayerComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(VideoPlayerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue