From 593c0fc6759c9d552589001aed0836e4da43ac80 Mon Sep 17 00:00:00 2001 From: ArabCoders Date: Fri, 10 Jan 2025 18:54:07 +0300 Subject: [PATCH] Fix and document presets.json --- README.md | 34 ++++++++++++++++++ app/library/config.py | 66 ++++++++++------------------------- app/library/presets.json | 54 ++++++++++++++++++++++++++++ ui/components/NewDownload.vue | 6 ++-- 4 files changed, 109 insertions(+), 51 deletions(-) create mode 100644 app/library/presets.json diff --git a/README.md b/README.md index 9dbbfd21..b2372764 100644 --- a/README.md +++ b/README.md @@ -301,6 +301,40 @@ The `config/webhooks.json`, is a json file, which can be used to add webhook end ] ``` +### presets.json File + +The `config/preset.json`, is a json file, which can be used to add custom presets for selection in WebUI. + +The file is supposed to be an array of objects, each object represent a preset, the schema for the object is as the following. +```json5 +[ + { + // (name: string) - REQUIRED - The preset name. + "name": "My super preset", + // (format: string) - REQUIRED - The required yt-dlp format. i.e. -f option in yt-dlp cli. + "format": "best", + // (postprocessors: array) - OPTIONAL - The postprocessors to run on the file. if it's preset or set to empty array, it will override the default postprocessors. + "postprocessors": [ + // for example to embed thumbnail. + { + "key": "EmbedThumbnail", + "already_have_thumbnail": false + } + ], + // (args: dict) - OPTIONAL - Extra yt-dlp arguments to pass to yt-dlp. + "args": { + // (key: string) - REQUIRED - The yt-dlp argument key. + "writethumbnail": true + } + }, + { + // another preset, etc... + } +] +``` + +For more expanded example please take look at the default presets file found in [app/library/presets.json](app/library/presets.json). + ## Authentication To enable basic authentication, set the `YTP_AUTH_USERNAME` and `YTP_AUTH_PASSWORD` environment variables. And restart the container. diff --git a/app/library/config.py b/app/library/config.py index 68553c28..980d4cc3 100644 --- a/app/library/config.py +++ b/app/library/config.py @@ -1,3 +1,4 @@ +import json import logging import os import re @@ -69,49 +70,7 @@ class Config: started: int = 0 ignore_ui: bool = False presets: list = [ - {"name": "default", "format": "default", "postprocessors": [], "args": {}}, - { - "name": "Best video and audio", - "format": "bv+ba/b", - "args": {}, - }, - { - "name": "1080p H264/m4a or best available", - "format": "bv[height<=1080][ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b[ext=webm]", - "args": { - "format_sort": ["vcodec:h264"], - }, - }, - { - "name": "720p h264/m4a or best available", - "format": "bv[height<=720][ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b[ext=webm]", - "args": { - "format_sort": ["vcodec:h264"], - }, - }, - { - "name": "Audio only", - "format": "bestaudio/best", - "postprocessors": [ - { - "key": "FFmpegExtractAudio", - "preferredcodec": "best", - "preferredquality": "5", - "nopostoverwrites": False, - }, - {"key": "FFmpegMetadata", "add_chapters": True, "add_metadata": True, "add_infojson": "if_exists"}, - {"key": "EmbedThumbnail", "already_have_thumbnail": False}, - {"key": "FFmpegConcat", "only_multi_video": True, "when": "playlist"}, - ], - "args": { - "outtmpl": {"pl_thumbnail": ""}, - "ignoreerrors": "only_download", - "retries": 10, - "fragment_retries": 10, - "writethumbnail": True, - "extract_flat": "discard_in_playlist", - }, - }, + {"name": "default", "format": "default"}, ] _manual_vars: tuple = ( @@ -276,15 +235,24 @@ class Config: except Exception: pass + # Load default presets. + with open(os.path.join(os.path.dirname(__file__), "presets.json"), "r") as f: + self.presets.extend(json.load(f)) + + # Load user defined presets. presetsFile = os.path.join(self.config_path, "presets.json") if os.path.exists(presetsFile) and os.path.getsize(presetsFile) > 0: - LOG.info(f"Loading extra presets from '{presetsFile}'.") + LOG.info(f"Loading user presets from '{presetsFile}'.") try: (presets, status, error) = load_file(presetsFile, list) if not status: LOG.error(f"Could not load presets file from '{presetsFile}'. '{error}'.") sys.exit(1) + if not isinstance(presets, list): + LOG.error(f"Invalid presets file '{presetsFile}'. It's expected to be a list of objects.") + sys.exit(1) + for preset in presets: if "name" not in preset: LOG.error(f"Missing 'name' key in preset '{preset}'.") @@ -294,11 +262,13 @@ class Config: LOG.error(f"Missing 'format' key in preset '{preset}'.") continue - if "args" not in preset: - preset["args"] = {} + if "args" in preset and not isinstance(preset["args"], dict): + LOG.error(f"Invalid 'args' key in preset '{preset}' it's expected to be dict.") + continue - if "postprocessors" not in preset: - preset["postprocessors"] = [] + if "postprocessors" in preset and not isinstance(preset["postprocessors"], list): + LOG.error(f"Invalid 'postprocessors' key in preset '{preset}' it's expected to be list.") + continue self.presets.append(preset) except Exception: diff --git a/app/library/presets.json b/app/library/presets.json new file mode 100644 index 00000000..e3223210 --- /dev/null +++ b/app/library/presets.json @@ -0,0 +1,54 @@ +[ + { + "name": "Best video and audio", + "format": "bv+ba/b" + }, + { + "name": "1080p H264/m4a or best available", + "format": "bv[height<=1080][ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b[ext=webm]", + "args": { + "format_sort": [ + "vcodec:h264" + ] + } + }, + { + "name": "720p h264/m4a or best available", + "format": "bv[height<=720][ext=mp4]+ba[ext=m4a]/b[ext=mp4]/b[ext=webm]", + "args": { + "format_sort": [ + "vcodec:h264" + ] + } + }, + { + "name": "Audio only", + "format": "bestaudio/best", + "args": { + "writethumbnail": true + }, + "postprocessors": [ + { + "key": "FFmpegExtractAudio", + "preferredcodec": "best", + "preferredquality": "5", + "nopostoverwrites": false + }, + { + "key": "FFmpegMetadata", + "add_chapters": true, + "add_metadata": true, + "add_infojson": "if_exists" + }, + { + "key": "EmbedThumbnail", + "already_have_thumbnail": false + }, + { + "key": "FFmpegConcat", + "only_multi_video": true, + "when": "playlist" + } + ] + } +] diff --git a/ui/components/NewDownload.vue b/ui/components/NewDownload.vue index c9cb8230..36f2a40e 100644 --- a/ui/components/NewDownload.vue +++ b/ui/components/NewDownload.vue @@ -60,14 +60,14 @@
+ placeholder="Uses default output template naming if empty.">
- All output format naming options can be found at this page.