Merge pull request #163 from arabcoders/dev

Fix and document presets.json
This commit is contained in:
Abdulmohsen 2025-01-10 19:05:47 +03:00 committed by GitHub
commit 2e99ff1f5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 109 additions and 51 deletions

View file

@ -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.

View file

@ -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:

54
app/library/presets.json Normal file
View file

@ -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"
}
]
}
]

View file

@ -60,14 +60,14 @@
<div class="field">
<label class="label is-inline" for="output_format"
v-tooltip="'Default Format: ' + config.app.output_template">
Output Format
Output Template
</label>
<div class="control">
<input type="text" class="input" v-model="output_template" id="output_format"
placeholder="Uses default output format naming if empty.">
placeholder="Uses default output template naming if empty.">
</div>
<span class="subtitle is-6">
All output format naming options can be found at <NuxtLink target="_blank" class="has-text-danger"
All output template naming options can be found at <NuxtLink target="_blank" class="has-text-danger"
href="https://github.com/yt-dlp/yt-dlp#output-template">this page</NuxtLink>.
</span>
</div>