From aa8a2d92dcc8f0222dfb93e10511fb7af2d13089 Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Sat, 19 Oct 2024 14:17:19 +0300 Subject: [PATCH] Feat/check input (#1089) * docs: instructions to set frames per seconds on sprites * feat: add more validation * remove reduntant line --- cms/settings.py | 5 +++++ docs/admins_docs.md | 17 +++++++++++++++-- files/tasks.py | 41 ++++++++++++++++++++++++++++++---------- uploader/fineuploader.py | 6 ++++++ 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/cms/settings.py b/cms/settings.py index f816b29..0e42a98 100644 --- a/cms/settings.py +++ b/cms/settings.py @@ -530,3 +530,8 @@ LANGUAGES = [ ] LANGUAGE_CODE = 'en' # default language + +SPRITE_NUM_SECS = 10 +# number of seconds for sprite image. +# If you plan to change this, you must also follow the instructions on admin_docs.md +# to change the equivalent value in ./frontend/src/static/js/components/media-viewer/VideoViewer/index.js and then re-build frontend \ No newline at end of file diff --git a/docs/admins_docs.md b/docs/admins_docs.md index f4038ec..f32ef86 100644 --- a/docs/admins_docs.md +++ b/docs/admins_docs.md @@ -21,6 +21,7 @@ - [18. Disable encoding and show only original file](#18-disable-encoding-and-show-only-original-file) - [19. Rounded corners on videos](#19-rounded-corners) - [20. Translations](#20-translations) +- [21. How to change the video frames on videos](#21-fames) ## 1. Welcome This page is created for MediaCMS administrators that are responsible for setting up the software, maintaining it and making modifications. @@ -833,10 +834,22 @@ After the string is marked as translatable, add the string to `files/frontend-tr python manage.py process_translations ``` -In order to populate the string in all the languages. NO PR will be accepted if this procedure is not followed. You don't have to translate the string to all supported languages, but the command has to run and populate the existing dictionaries with the new strings for all languages. This ensures that there is no missing string to be translated in any language. +In order to populate the string in all the languages. NO PR will be accepted if this procedure is not followed. You don't have to translate the string to all supported languages, but the command has to run and populate the existing dictionaries with the new strings for all languages. This ensures that there is no missing string to be translated in any language. After this command is run, translate the string to the language you want. If the string to be translated lives in Django templates, you don't have to re-build the frontend. If the change lives in the frontend, you will have to re-build in order to see the changes. The Makefile command `make build-frontend` can help with this. ### 20.5 Add a new language and translate -To add a new language: add the language in settings.py, then add the file in `files/frontend-translations/`. Make sure you copy the initial strings by copying `files/frontend-translations/en.py` to it. \ No newline at end of file +To add a new language: add the language in settings.py, then add the file in `files/frontend-translations/`. Make sure you copy the initial strings by copying `files/frontend-translations/en.py` to it. + + +## 21. How to change the video frames on videos + +By default while watching a video you can hover and see the small images named sprites that are extracted every 10 seconds of a video. You can change this number to something smaller by performing the following: + +* edit ./frontend/src/static/js/components/media-viewer/VideoViewer/index.js and change `seconds: 10 ` to the value you prefer, eg 2. +* edit settings.py and set the same number for value SPRITE_NUM_SECS +* now you have to re-build the frontend: the easiest way is to run `make build-frontend`, which requires Docker + +After that, newly uploaded videos will have sprites generated with the new number of seconds. + diff --git a/files/tasks.py b/files/tasks.py index 2255b65..5e6f3be 100644 --- a/files/tasks.py +++ b/files/tasks.py @@ -374,14 +374,28 @@ def produce_sprite_from_video(friendly_token): try: tmpdir_image_files = tmpdirname + "/img%03d.jpg" output_name = tmpdirname + "/sprites.jpg" - cmd = "{0} -i {1} -f image2 -vf 'fps=1/10, scale=160:90' {2}&&files=$(ls {3}/img*.jpg | sort -t '-' -n -k 2 | tr '\n' ' ')&&convert $files -append {4}".format( + + fps = getattr(settings, 'SPRITE_NUM_SECS', 10) + ffmpeg_cmd = [ settings.FFMPEG_COMMAND, - media.media_file.path, - tmpdir_image_files, - tmpdirname, - output_name, - ) - subprocess.run(cmd, stdout=subprocess.PIPE, shell=True) + "-i", media.media_file.path, + "-f", "image2", + "-vf", f"fps=1/{fps}, scale=160:90", + tmpdir_image_files + ] + run_command(ffmpeg_cmd) + image_files = [f for f in os.listdir(tmpdirname) if f.startswith("img") and f.endswith(".jpg")] + image_files = sorted(image_files, key=lambda x: int(re.search(r'\d+', x).group())) + image_files = [os.path.join(tmpdirname, f) for f in image_files] + cmd_convert = [ + "convert", + *image_files, # image files, unpacked into the list + "-append", + output_name + ] + + run_command(cmd_convert) + if os.path.exists(output_name) and get_file_type(output_name) == "image": with open(output_name, "rb") as f: myfile = File(f) @@ -421,12 +435,19 @@ def create_hls(friendly_token): existing_output_dir = output_dir output_dir = os.path.join(settings.HLS_DIR, p + produce_friendly_token()) files = " ".join([f.media_file.path for f in encodings if f.media_file]) - cmd = "{0} --segment-duration=4 --output-dir={1} {2}".format(settings.MP4HLS_COMMAND, output_dir, files) - subprocess.run(cmd, stdout=subprocess.PIPE, shell=True) + cmd = [ + settings.MP4HLS_COMMAND, + '--segment-duration=4', + f'--output-dir={output_dir}', + files + ] + run_command(cmd) + if existing_output_dir: # override content with -T ! cmd = "cp -rT {0} {1}".format(output_dir, existing_output_dir) - subprocess.run(cmd, stdout=subprocess.PIPE, shell=True) + run_command(cmd) + shutil.rmtree(output_dir) output_dir = existing_output_dir pp = os.path.join(output_dir, "master.m3u8") diff --git a/uploader/fineuploader.py b/uploader/fineuploader.py index bcf7a23..a069a9d 100644 --- a/uploader/fineuploader.py +++ b/uploader/fineuploader.py @@ -10,6 +10,11 @@ from django.conf import settings from . import utils +def strip_delimiters(input_string): + delimiters = " \t\n\r'\"[]{}()<>\\|&;:*-=+" + return ''.join(char for char in input_string if char not in delimiters) + + def is_valid_uuid_format(uuid_string): pattern = re.compile(r'^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$', re.IGNORECASE) return bool(pattern.match(uuid_string)) @@ -28,6 +33,7 @@ class BaseFineUploader(object): self.uuid = uuid.uuid4() self.filename = os.path.basename(self.filename) + self.filename = strip_delimiters(self.filename) # avoid possibility of passing a fake path here self.file = data.get("qqfile")