Merge pull request #311 from ArabCoders/master

Support loading YTDL_OPTIONS from file
pull/324/head
Alex 2023-08-19 23:28:37 +02:00 committed by GitHub
commit 0adb85b10f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 2 deletions

View File

@ -50,6 +50,7 @@ Certain values can be set via environment variables, using the `-e` parameter on
* __OUTPUT_TEMPLATE__: the template for the filenames of the downloaded videos, formatted according to [this spec](https://github.com/yt-dlp/yt-dlp/blob/master/README.md#output-template). Defaults to `%(title)s.%(ext)s`.
* __OUTPUT_TEMPLATE_CHAPTER__: the template for the filenames of the downloaded videos, when split into chapters via postprocessors. Defaults to `%(title)s - %(section_number)s %(section_title)s.%(ext)s`.
* __YTDL_OPTIONS__: Additional options to pass to youtube-dl, in JSON format. [See available options here](https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/YoutubeDL.py#L183). They roughly correspond to command-line options, though some do not have exact equivalents here, for example `--recode-video` has to be specified via `postprocessors`. Also note that dashes are replaced with underscores.
* __YTDL_OPTIONS_FILE__: A path to a JSON file that will be loaded and used for populating `YTDL_OPTIONS` above. Please note that if both `YTDL_OPTIONS_FILE` and `YTDL_OPTIONS` are specified, the options in `YTDL_OPTIONS` take precedence.
The following example value for `YTDL_OPTIONS` embeds English subtitles and chapter markers (for videos that have them), and also changes the permissions on the downloaded video and sets the file modification timestamp to the date of when it was downloaded:

View File

@ -27,6 +27,7 @@ class Config:
'OUTPUT_TEMPLATE': '%(title)s.%(ext)s',
'OUTPUT_TEMPLATE_CHAPTER': '%(title)s - %(section_number)s %(section_title)s.%(ext)s',
'YTDL_OPTIONS': '{}',
'YTDL_OPTIONS_FILE': '',
'HOST': '0.0.0.0',
'PORT': '8081',
'BASE_DIR': '',
@ -38,6 +39,7 @@ class Config:
def __init__(self):
for k, v in self._DEFAULTS.items():
setattr(self, k, os.environ[k] if k in os.environ else v)
for k, v in self.__dict__.items():
if v.startswith('%%'):
setattr(self, k, getattr(self, v[2:]))
@ -46,8 +48,10 @@ class Config:
log.error(f'Environment variable "{k}" is set to a non-boolean value "{v}"')
sys.exit(1)
setattr(self, k, v in ('true', 'True', 'on', '1'))
if not self.URL_PREFIX.endswith('/'):
self.URL_PREFIX += '/'
try:
self.YTDL_OPTIONS = json.loads(self.YTDL_OPTIONS)
assert isinstance(self.YTDL_OPTIONS, dict)
@ -55,6 +59,20 @@ class Config:
log.error('YTDL_OPTIONS is invalid')
sys.exit(1)
if self.YTDL_OPTIONS_FILE:
log.info(f'Loading yt-dlp custom options from "{self.YTDL_OPTIONS_FILE}"')
if not os.path.exists(self.YTDL_OPTIONS_FILE):
log.error(f'File "{self.YTDL_OPTIONS_FILE}" not found')
sys.exit(1)
try:
with open(self.YTDL_OPTIONS_FILE) as json_data:
opts = json.load(json_data)
assert isinstance(opts, dict)
except (json.decoder.JSONDecodeError, AssertionError):
log.error('YTDL_OPTIONS_FILE contents is invalid')
sys.exit(1)
self.YTDL_OPTIONS.update(opts)
config = Config()
class ObjectSerializer(json.JSONEncoder):
@ -140,13 +158,13 @@ def get_custom_dirs():
dirs = list(filter(None, map(convert, path.glob('**'))))
return dirs
download_dir = recursive_dirs(config.DOWNLOAD_DIR)
audio_download_dir = download_dir
if config.DOWNLOAD_DIR != config.AUDIO_DOWNLOAD_DIR:
audio_download_dir = recursive_dirs(config.AUDIO_DOWNLOAD_DIR)
return {
"download_dir": download_dir,
"audio_download_dir": audio_download_dir